C踩坑紀實——(一)

最近在項目過程中發現了幾個c語言中沒有注意到的小細節,成功入坑。下面記錄的我遇到的問題,以及解決的方法,希望這個過程能給讀者帶來些許啟發。

字元類型變數的溢出

首先來看下面這段程式碼,你認為會輸出什麼呢?

int remain = 129
do{
	char d = remain%128;
	remain /= 128;
	if(remain > 0)
		d |= 0X80;
	*s++ = d;
}while(remain > 0);
printf("str:%x\r\n",*str);

你也許會和我的想法相同,這返回不是81么?要是一眼就被看出來我也就不會記錄下來了,往往我們定義數據類型時都忽略了2個問題,數據類型的取值範圍與加unsigned與不加的區別,下面就通過這個例子來聊聊這兩點。
先揭曉答案,這段偽程式碼的返回FFFFFF81,為什麼呢? 因為char類型佔1個位元組的大小,其取值範圍為-128~127,1+(-128)=-127,而在電腦中,負數是由補碼錶示,也就是我們看到FFFFFF81,在電腦中表示-127,而81,在電腦中表示正數129,也許還有個疑問,char類型佔1位元組大小,而FFFFFF81佔了4位元組大小,這不是空間溢出了么? 其實並沒有,當變數是負數時,在電腦中由32位表示,但其所佔的空間記憶體還是一位元組
如果*s的數據類型是unsigned char結果又是什麼呢? 沒錯,這回就真是81了,因為unsigned char的取值範圍為0~255。是不是若有所思呢?下面來檢驗下收穫吧,請看下面程式碼

short int a=1234;
short int *p=&a;
char *q=(char *)p;
char *k=(char *)p+1;
printf("address:%p--%p--%p\n",p,q,k);
printf("value:%x--%x--%x\n",*p,*q,*k);

實驗寫出上面程式碼的輸出結果吧!

二維數組賦值

二維數組賦值,你知道幾種方法呢,用for循環逐個完成、初始化時完成,使用下面的賦值方式你覺得怎麼樣呢?

char a[100][128];
char *topic = "matt test";

a[0] = topic;

printf("a[0]:%s\r\n",a[0])

上面偽程式碼是個錯誤的例子,因為數組首地址不可被改變這條規則,所以編譯器不會通過這段程式碼。如果用數組首地址對數組賦值,有什麼方便的方法呢? 見下面程式碼

char a[100][128];
char *topic = "matt test";

memset(a,0x0,sizeof(a));
memcpy(a[0],topic,strlen(topic));

printf("a[0]:%s\r\n",a[0])

指針地址變化

C語言中,指針是一大精華,也是一個難點,使用不當容易造成記憶體泄漏,使系統不穩定。若對已初始化但未分配記憶體空間的指針寫值,易造成segmentation fault(段錯誤)。下面指針的地址你清楚么?

short int a=1234;
short int *p=&a;
char *q=(char *)p;
printf("address:%p--%p--%p--%p\n",p,p+1,q,q+1);

指針地址的變化與指針的的數據類型相關,而在不同作業系統中,數據類型也有所不同,在64位Windows與linux系統中,char與int分別佔1位元組與4位元組記憶體空間,故(P+1)-p為4,(q+1)-q為1.

清風 | 文 【原創】

如果本篇部落格有任何錯誤,請批評指教,不勝感激 !