printf("%f", 5);
上面語句打出的結(jié)果為0.000000。原因是printf根據(jù)%f會(huì)認(rèn)為參數(shù)是double型,因此從棧中讀8個(gè)字節(jié)。而5是int型,內(nèi)存訪問越界,發(fā)生不可預(yù)料的情況,處理時(shí)打印0。
//結(jié)構(gòu)體位制
struct a{
int x : 1; //這種語法是指定x的bit位數(shù),所以x只有1位
int y : 2;
int z : 33; //z指定33位,但因?yàn)槭莍nt只有32位,所以報(bào)錯(cuò)
}
下面代碼哪個(gè)等同于int i=(int) p; (p類型為char *)?
A int i = dynamic_cast<int>(p)
B int i = static_cast<int>(p)
C int i = const_cast<int>(p)
D int i=reinterpret_cast<int>(p)
選D,dynamic_cast用于父類子類間的指針類型轉(zhuǎn)換,static,const的功能也用于這,只有reinterpret_cast(不改變原數(shù)據(jù)的值),這里是將指針p的值(某地址)按int賦值給i。
static_cast, const_cast, dynamic_cast, reinterpret_cast
static_cast用于類型轉(zhuǎn)換,如將int轉(zhuǎn)換為double以便讓包含int的表達(dá)式產(chǎn)生浮點(diǎn)數(shù)值的結(jié)果。
static_cast<double>(firstNumber)/secondNumber
不能用于將double轉(zhuǎn)為指針或者struct轉(zhuǎn)int,不能去除const屬性。
const_cast最普通的用途就是去掉對(duì)象的const屬性。
class B{
public:
int m_iNum;
};
int main(){
B b0;
b0.m_iNum=100;
const B b1=b0;
cout<<b0.m_iNum<<" "<<b1.m_iNum<<endl;
const_cast<B&>(b1).m_iNum=200;
cout<<b0.m_iNum<<" "<<b1.m_iNum<<endl;
return 0;
}
static_cast和reinterpret_cast操作修改了操作數(shù)類型。static_cast編譯時(shí)使用類型信息執(zhí)行轉(zhuǎn)換,相對(duì)安全。reinterpret_cast僅僅是重新解釋對(duì)象的比特模型,沒有進(jìn)行二進(jìn)制轉(zhuǎn)換,比較危險(xiǎn)。
int n=9;
static_cast<double>(n); //這里會(huì)為n補(bǔ)位
reinterpret_cast<double>(n); //不會(huì)補(bǔ)位
dynamic_cast使用需要注意
- dynamic_cast是在運(yùn)行時(shí)檢查,用于進(jìn)行安全的向下轉(zhuǎn)換。如果源和目標(biāo)類型沒有繼承和被繼承關(guān)系,編譯器會(huì)報(bào)錯(cuò);必須判斷返回值是否為NULL來確認(rèn)轉(zhuǎn)換是否成功。
- dynamic_cast是4個(gè)轉(zhuǎn)換中唯一的RTTI操作符,提供運(yùn)行時(shí)類型檢查。
- dynamic_cast不是強(qiáng)制轉(zhuǎn)換,而是咨詢性質(zhì)的轉(zhuǎn)換,不能轉(zhuǎn)換的話返回NULL。
對(duì)于類中的成員函數(shù),如果不涉及類成員變量,則即使該類的指針為NULL時(shí),也可以通過該指針調(diào)用該成員函數(shù)。
class B{
public:
void disp(){ cout<<"hello world"<<endl; }
};
int main(){
B *b0=NULL;
b0->disp();
return 0;
}
但如果該類繼承了父類,且該方法為虛函數(shù),則調(diào)用會(huì)出錯(cuò),因?yàn)檎{(diào)用虛方法要求對(duì)象有一個(gè)虛函數(shù)表指針。
class A{
public:
virtual void disp(){ cout<<"hello A"<<endl; }
};
class B : public A{
public:
virtual void disp(){ cout<<"hello B"<<endl; }
};
int main(){
B *b0=NULL;
b0->disp();
return 0;
}
建立一個(gè)聯(lián)合體,由char和int類型組成
union{
unsigned char a;
unsigned int i;
}u;
u.i=0xf0f1f2f3;
cout<<hex<<u.i<<endl; //輸出f0f1f2f3
cout<<hex<<u.a<<endl; //輸出f3
說明內(nèi)存中數(shù)據(jù)低位字節(jié)存入低地址,高位字節(jié)存入高地址,數(shù)據(jù)的地址采用它的低地址表示。
當(dāng)一個(gè)變量的值可能會(huì)在編譯器的控制或監(jiān)測之外被改變時(shí),那么它應(yīng)該聲明為volatile。因此編譯器執(zhí)行的例行優(yōu)化行為不能應(yīng)用在該指定為volatile變量上。這樣,優(yōu)化器在用到這個(gè)變量時(shí)都必須每次的重新讀取這個(gè)變量的值,而不是使用保存在寄存器的備份。
可以建立const volatile變量,這樣這個(gè)變量不能被程序員改變,但可以通過外面的工具改變。
const意味著“只讀”。
下面的函數(shù)有什么錯(cuò)誤?
int square(volatile int *ptr){ return *ptr * *ptr; }
上面的代碼本意是返回ptr的平方,但由于執(zhí)行時(shí)ptr可能會(huì)改變,類似于下面的代碼
int square(volatile int *ptr){
int a=*ptr;
int b=*ptr;
return a*b;
}
正確的應(yīng)該如下
int square(volatile int *ptr){
int a=*ptr;
return a*a;
}
小尾字節(jié)序和大尾字節(jié)序
前者是指CPU對(duì)操作數(shù)的存放方式是從低字節(jié)到高字節(jié)即低位字節(jié)存放在低地址,高位字節(jié)存放在高地址。后者則相反,低地址存高位字節(jié),高地址存低位字節(jié)。
或者解釋為,沿著地址向上的方向,小尾先存低后存高;大尾先存高后存底。
//存儲(chǔ)0x1234
//小尾
0x4000 0x34
0x4001 0x12
//大尾
0x4000 0x12
0x4001 0x34
static關(guān)鍵字的作用: