1:一維數組:數組名相當于當前類型的一個指針,而且為const的指針,指向(指針里面的內容)不可變。
2:一維數組和二維數組的內存分布是完全一樣的,但是還是有不同。首地址+1的時候,一位數組加的數組類型的大小,二位數組加的是第二維大小*數據類型大小(類型為數組類型)。#include <stdio.h>int main(){ int array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int other[2][5] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; PRintf("%p/t%p/n", array, array + 1); //后者 +1*sizeof(*array) = +4 printf("%p/t%p/n", other, other + 1); //后者 +1*sizeof((*array)[5]) = +20 return 0;}3:上面二維數組的時候用數組名+1實際上是加上數組類型的大小。在以為數組名前面加&符號得到的實際上也是數組類型。
注意:數組類型實際上是由兩個因素決定的:
1:元素類型 2:數組大小。任何一個數組都存在其數組類型。
下面是數組指針的用法: int array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int (*parray)[10] = &array; //前面的就是數組指針,它指向的是數組類型 printf("%p/t%p/n", parray, parray + 1); //這里 +1 實際上是 + 1*sizeof(*(parray[10])) = +40;
4:平時使用數組指針不會像上面這種方式定義。可以使用typedef來定義。
#include <stdio.h>typedef int (INT10)[10]; //數組類型int main(){ int array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int other[2][5] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; printf("%p/t%p/n", array, array + 1); //后者 +1*sizeof(*array) = +4 printf("%p/t%p/n", other, other + 1); //后者 +1*sizeof(*(array[5])) = +20 int (*parray)[10] = &array; //前面的就是數組指針,它指向的是數組類型 printf("%p/t%p/n", parray, parray + 1); //這里 +1 實際上是 + 1*sizeof(*(parray[10])) = +40; INT10 *intarray = &array; printf("%d/n", sizeof(INT10)); //40 printf("%p/t%p/n", intarray, intarray + 1); //+1 = +40byte return 0;}5:數組指針兩個比較重要的因素:元素類型,數組大小
注意:定義數組指針的時候,數組大小必須要吻合(warning C4048: “int (*)[5]”和“int (*)[10]”數組的下標不同),類型也應該吻合(warning C4133: “初始化”: 從“int (*)[10]”到“char (*)[10]”的類型不兼容),否則會產生警告。
6:二維數組里面的第一個維度相當于就是存儲的數組指針,他們指向的是多個以而為下標大小的數組類型。+1也就是加的二維的大小。
下面的代碼可以更好的讓我們理解數組指針:
#include <stdio.h>void foo(int (*array)[10]) //定義成數組指針,這樣才是接收常量數組指針最正確的方式。二維的寫兩個[][]。{}int main(){ int array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int other[2][5] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };// foo(array); //array -> 常量指針(int * const)// foo(other); //other -> 常量指針(int(*)[5]) foo(&array); //&array -> 常量數組指針(int(*)[10])// foo(&other); //&other -> 常量數組指針(int(*)[2][5]) return 0;}指針數組:
1:指針數組就是存放指針的數組,很好理解。一個數組,它里面有很多個指針。#include <stdio.h>int main(){ char *key1s[10] = { "aaa", "bbb", "ccc" }; //這種就是指針數組,就是一個存放指針的數組。 //上面這個指針數組可以存放10個字符指針,字符串可以存放的長度和這個沒有任何關系。字符串有多長和指針無關。 char key2s[100][100] = { 0 }; //這里面可以存放(管理)100個字符串,能夠存放的字符串長度可以是10000(-1)。 return 0;} 注意:上面程序的key1s和key2s的區別:key1s是只可讀的,key2s是可讀寫的。key1s為指針數組,key2s為字符數組,C語言是沒有字符串類型。2:不同初始化方式保存的位置以及是否可改:#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#include <string.h>int main(){ char *key1s[10] = { "aaa", "bbb", "ccc" }; //這種就是指針數組,就是一個存放指針的數組。 //上面這個指針數組可以存放10個字符指針,字符串可以存放的長度和這個沒有任何關系。字符串有多長和指針無關。 char key2s[100][100] = { 0 }; //這里面可以存放(管理)100個字符串,能夠存放的字符串長度可以是10000(-1)。// 指針可改? 數據可改? //堆區: char *str1 = malloc(100 * sizeof(char)); //可改 可改 //棧區: char str2[100]; //不可改 可改 //常量區: char *str3 = ""; //可改 不可改 char *str4 = str1; strcpy(str4, "100"); //可改 正確操作 char *str5 = str3; strcpy(str5, "100"); //不可改 錯誤操作 在常量區 char *str6 = str2; str6[10] = '1'; //可改 正確操作 return 0;}3:指針數組的參數傳遞實際上是傳遞的指針的指針。傳參為二級指針。#include <stdio.h>void foo(char *key[])//傳遞過來的是指針數組的首元素地址。是拷貝過來的。{ printf("%s/n", key[1]);//bbb printf("%s/n", key[2]);//ccc printf("%s/n", key[3]);//<null> char *str = "123456"; key[1] = str; printf("%s/n", key[1]);//123456}int main(){ char *key1s[10] = { "aaa", "bbb", "ccc" }; foo(key1s); //key1s 首元素類型 char** //&key1s 數組指針 char*(*)[10] 指針數組的數組指針 return 0;}4:指針數組在main函數里面就有運用,真實的main函數織機上是這樣的:#include <stdio.h>//main函數實際上為操作系統調用。操作系統默認會傳遞幾個參數進去。int main(int argc, char* argv[], char* env[])//argc是argv的數量,argv是操作系統傳遞的參數,env是環境變量。{ for (int i = 0; i < argc; ++i) { printf("%s/n", argv[i]); } //操作系統傳遞的參數一是文件路徑。 //還可以在exe的快捷方式里目標的最后加上字符串 也可以傳遞進來。 //還可以通過cmd執行的時候,在后面加上一些參數 int i = 0; while (env[i] != NULL) { printf("%s/n", env[i++]); } return 0;}函數指針:
1:函數也有自己的類型,函數指針主要用于做回調函數以及函數的路由等。#include <stdio.h>int Foo(int one, int two)//函數類型是 int(*pfoo)(int, int){ return one + two;}void Foo2()//函數類型是 void(*pfoo2){}typedef int FOOTYPE(int, int);//可以定義函數類型,int main(){ void *pFoo = &Foo; int(*pfoo)(int, int) = Foo;//int(*pfoo)(int, int) = &Foo;//這里加&和不加&是完全一樣的,這里與變量不一樣。 void(*pfoo2) = Foo2;// printf("%d/r/n", pFoo(1, 2)); //不知為什么出錯 printf("%d/r/n", pfoo(1, 2)); FOOTYPE *p = &Foo; //使用typedef定義的類型來申請指針。 printf("%d/r/n", p(2, 3)); return 0;}2:typedef定義的函數類型是可以當作參數來使用的,能夠在外部來傳遞,調用指定的方法#include <stdio.h>typedef int FOOTYPE(int, int);//可以定義函數類型int Foo(int one, int two)//函數類型是 int(*pfoo)(int, int){ return one + two;}void Foo2()//函數類型是 void(*pfoo2){}typedef void (FUNCERROR)(int);void PrintError(int code){ printf("Error: %d", code);}void SetValue(char*array[], char*value, FUNCERROR *error){ if (array == NULL) error(100);}int main(){ void *pFoo = &Foo; int(*pfoo)(int, int) = Foo;//int(*pfoo)(int, int) = &Foo;//這里加&和不加&是完全一樣的,這里與變量不一樣。 void(*pfoo2) = Foo2;// printf("%d/r/n", pFoo(1, 2)); //不知為什么出錯 printf("%d/r/n", pfoo(1, 2));//可以看出調用和普通的函數調用區別不大 FOOTYPE *p = &Foo; //使用typedef定義的類型來申請指針。 printf("%d/r/n", p(2, 3)); SetValue(NULL, NULL, PrintError);//會打印error: 100 return 0;}復習:



新聞熱點
疑難解答