http://blog.csdn.net/unix21/article/details/16116737 2013 說明文中*p++和*s++都是一個東西,不做字面上的統(tǒng)一了。 因為右結(jié)合性,*p++ 其實就是 *(p++)
1.strlen的實現(xiàn)
遞增到最后一位就是\0,也就是“”. 注意:*s已經(jīng)指向后面的內(nèi)容了,就是亂碼了 2.數(shù)組和指針這2種方式表示字符串的差異
2.1 數(shù)組不能直接當(dāng)指針用,數(shù)組名不能指針運算 也就是說數(shù)組名代表數(shù)組的首元素,它是一個指針常量,它的值在程序運行期間是固定不變的, *str++是不可以的; ptr是指針變量當(dāng)然可以實現(xiàn)ptr++的運算但是指針自然可以指針運算。 直接數(shù)組名++就報錯了: 2.2 數(shù)組名不能直接賦值,但是指針可以 給數(shù)組名賦值就報錯了: 第1次指針地址是:0x010f5860 第2次指針地址是:0x010f5861 第3次指針地址是:0x010f5868 第4次指針地址還是:0x010f5868 下面是《明解C語言》書的截圖: 3. int下*s++,(*s)++,++*s,++(*s)的差異 首先 如果*s是指針,那么*s++就不是將*s的值加1,而是將*s指向的地址加同一個單位大小。所以為了避免類似問題,需要的時候要加括號。 --出自《C語言入門經(jīng)典 第4版》
第1次*s++之前的地址是:0x002afc98 第2次*s++之前的地址是:0x002afc9c fc9c-fc98=4 就是一個int的大小 *s++只是對s的地址遞增然后解引用,得到-858993460,并沒有改變*s的值! 跳出函數(shù)a沒有變化 所以要想得到Int型值的遞增可以這樣寫即可:
由于char*大小正好是1個字節(jié),所以char*的++正好指向下一個字符! 所以在字符串的操作中正好可以用*s++,如果使用了括號,(*s)++這樣的話反而會引起內(nèi)存錯誤。 4.字符串復(fù)制
--出自《C語言程序設(shè)計語言 第2版》 5.說清楚函數(shù)傳遞參數(shù) 一開始我們會想既然已經(jīng)在函數(shù)中*s++了,而且也確實改變了指針的位置,但是為什么一回到調(diào)用函數(shù)中,*s就又復(fù)原了? 不是說傳指針是按引用傳遞的么? 其實,誤區(qū)也正在于此,函數(shù)還是傳值的,傳遞的都是原值的拷貝,如果傳遞指針,在調(diào)用函數(shù)中使用*解引用,可以改變指針指向的值,但是不能改變指針的內(nèi)容,因為函數(shù)調(diào)用只是傳遞了原始指針指向值地址的拷貝,就是說原始地址拷貝了2份,所以在函數(shù)中改變是改變了地址,但是沒有意義。
int a = 0x55aa; change_value(&a, 0xaa55); 這樣a的值改變了,真正的情況是參數(shù)傳遞后,編譯器做了一個參數(shù)拷貝過程,比如聲明一個整型指針pCopy = &a; 這樣,pCopy只是傳進來參數(shù)&a的一份拷貝,但是他們都指向了a的地址,因此用這種方法可以改變a 的值。 那么現(xiàn)在有個問題,通過傳遞一個指針,可以改變該指針?biāo)赶虻刂返膬?nèi)容,那么如何改變指針本身呢? 該怎么做才能改變ptr呢? 既然ptr也是一個變量,我要在函數(shù)內(nèi)部改變它,那么就傳遞一個指向ptr的指針!也就是二級指針!
6.函數(shù)返回指針 絕不返回函數(shù)中本地變量的地址。
函數(shù)返回指針可以用如下方法: 1.可以用malloc分配內(nèi)存,并返回這個內(nèi)存的地址 2.返回指針參數(shù)
注意函數(shù)中可以聲明一個新的結(jié)構(gòu)struct,然后返回結(jié)構(gòu),但是不可以返回臨時指針。
7.數(shù)組和指針的差異 數(shù)組不是指針,作為參數(shù)傳遞的數(shù)組會退化為指針。 為什么C語言把數(shù)組形參當(dāng)做指針? 再來看看《你必須知道的495個C語言問題》 8.數(shù)組不能被賦值 數(shù)組不能賦值,可以指定數(shù)組下標(biāo)賦值,可以在函數(shù)中可以給數(shù)組賦值,因為這個時候數(shù)組退化為指針。 9.數(shù)組的大小 10.指針和結(jié)構(gòu) 結(jié)構(gòu)體指針4個字節(jié),結(jié)構(gòu)體大小要看數(shù)據(jù)對齊。 分配12個字節(jié),結(jié)構(gòu)吃掉8個,當(dāng) (結(jié)構(gòu)地址+1)所以只能第一個元素可以分配到初始化的0,第二個元素就分到垃圾地址了
指針不對齊8a88 和8a90差2 8a90和8a98差8 結(jié)構(gòu)有2個Int 所以結(jié)構(gòu)大小是8 結(jié)構(gòu)和指針的關(guān)系 對同一個地址可以轉(zhuǎn)換為任意結(jié)構(gòu)體,雖然數(shù)據(jù)結(jié)構(gòu)亂了,但是畢竟也是有數(shù)據(jù)。 所以使用法則也就是使用前先尋址,再強制轉(zhuǎn)換 11.變量作用域 局部變量的作用域一般認(rèn)為是在函數(shù)體內(nèi)。但是根據(jù)C99標(biāo)準(zhǔn),該說法有了變化。在新的標(biāo)準(zhǔn)中,允許即時定義局部變量,示例如下: for( int i = 0; i < MAXSIZE; i++ ) { …. } 例子中的局部變量i的作用域即在for循環(huán)的花括號中,當(dāng)for循環(huán)結(jié)束的時候,局部變量i的生存周期同時結(jié)束。也就是說,在下一個for循環(huán)中,你仍然可以再次重新定義并使用名為i的局部變量。該語法只能在C99之后的新的C編譯器中使用, 例如VC2005、VC2008、gcc4.2及以上版本。但是,該語法帶來了編程風(fēng)格的變化,而且變量隱含在了執(zhí)行程序中,無論是代碼的閱讀和維護都有較大的困難,因此工程項目中不建議使用該語法。 for循環(huán)中定義的pit 在離開循環(huán)以后就不存在了。 12.傳遞結(jié)構(gòu)和數(shù)組給函數(shù)的差異 為什么傳遞給函數(shù)的結(jié)構(gòu)沒有像數(shù)組一樣退化為指針,因為數(shù)組可以用指針去偏移量,但是結(jié)構(gòu)無法做到這一點,或者說非常困難。 其實函數(shù)參數(shù)默認(rèn)是通過r0,r1,r2,r3四個寄存器傳遞的,多余的參數(shù)是通過將參數(shù)壓入棧中傳遞的。同理對于一個結(jié)構(gòu)體如果其大小少于32字節(jié)(4個寄存器),按照正常的方式通過r0到r3傳遞,多于32字節(jié)則是將多余的部分在堆棧上建立個備份進行傳遞。 所以對于在ADS編譯器下對于函數(shù)參數(shù)是結(jié)構(gòu)體的傳遞,還是傳入指針比較好。既高效(省去建立備份的時間),又節(jié)省??臻g。
13.指針大小 32位是4個字節(jié),32=4*8 64位是8個字節(jié),64=8*8 在64位的linux下: 而visual studio里默認(rèn)是win32平臺,指針是4個字節(jié)大?。?/p>
需要修改為x64平臺 這時候顯示指針是8個字節(jié): 14.指向數(shù)組的指針 slabclass_t *p = &slabclass[id]; |
|