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