1、数组初始化:
数组元素的个数可以显示或隐式指定
int main() { int a[10] = {1,2};//其他没初始化元素,编译器默认帮你初始化为0 int b[] = {1, 2};//编译器隐式指定长度为两个元素 int c[20] = {0}; for (i=0; i<10; i++) { printf("%d ", a[i]); } memset(a, 0, sizeof(a)); getchar(); }
|
2、数组名理解难点
int a[10]={1,2}; printf("&a:%d,a:%d\n",&a,a); printf("&a+1:%d,a+1:%d\n", &a+1, a+1); |
-
数组首元素地址与数组地址:数组名a代表元素首地址,&a代表数组地址。
-
数组首元素地址=数组地址即:a=&a
-
&a+1代表的是加一个数组长度sizeof(a),a+1代表的是加一个数组元素长度sizeof(a[0])
-
一维数组名是一个指针常量
-
二维数组名是一个数组指针,多维数组名也是一个数组指针,是指向一个低维数组的指针
char array[10][30]; (array+i) //相当于第i行的首地址 //二级指针 (*(array+i)) //一维数组的首地址 //一级指针 *(array+i)+j //相当于第i行第j列的地址 &array[i][j] *(*(array+i)+j) //相当于第i行第j列的地址 array[i][j] |
6、多维数组在物理内存中是线性存储的,只是编译器帮我们优化了
|
2、初学者数组类型三大难题
数组类型
数组指针:数组是一个指针,该指针是指向一个数组的指针(数组类型和数组指针的关系)
指针数组:指针是数组元素,也就是数组元素中存储的都是指针
1、 数组类型
C语言中的数组有自己特定的类型,数组的类型由元素类型和数组大小共同决定
1、定义一个数组类型:用数组定义变量
void main12() { int i = 0; //定义一个数组类型 typedef int MyArrayType[5]; //int MyArrayType myArray; //int myArray[5]; for (i=0; i<5; i++) { myArray[i] = i +1; } for (i=0; i<5; i++) { printf("%d \n", myArray[i]); } system("pause"); } |
2、定义一个数组类型,用数组顶一个数组类型的指针
void main13() { int i = 0; typedef int MyArrayType[5]; //定义一个数组类型 MyArrayType *pArray = NULL; //定义了一个数组类型的指针 Int a[5]={0}; pArray = &a; for (i=0; i<5; i++) //我通过数组指针的方式来操作a[5]这块内存 { (*pArray)[i] = i+1; //a[i] = i+1; } for (i=0; i<5; i++) { printf("%d \n", (*pArray)[i]); } system("pause"); } |
2、 数组指针
定义数组指针
int i = 0; //这个是定义了一个类型,这个类型是数组类型 typedef int MyArrayType[5]; //int //这个是定义了一个类型,定义了一个指针类型,定义了一个指向数组的指针类型。。。。 typedef int (*MyPArrType)[5] ; //数组指针 MyPArrType myPoint; // int b[5]; myPoint = &b; //变量取地址给指针赋值 for (i=0; i<5; i++) { (*myPoint)[i] = i+1; } for (i=0; i<5; i++) { printf("%d ", (*myPoint)[i]); } system("pause"); } |
1):typedef int MyArrayType[5]; //定义一个数组类型 MyArrayType *pArray = NULL; //定义了一个数组类型的指针 //这个是定义了一个类型,定义了一个指针类型,定义了一个指向数组的指针类型 2):typedef int (*MyPArrType)[5] ; //数组指针 MyPArrType myPoint; //int b[5]; 3):int (*myArrayPoint)[5] ; //告诉编译给我开辟四个字节内存 |
5、指针数组
1、指针数组与数组指针容易混淆
Char *p1[] = {“123”,”456”,”789”}; []优先级高,先与p结合成为一个数组,再由char*说明这是一个字符型指针数组 //这是一个指针数组、数组3*4、三个一维数组的首地址存放在以指针作为元素的数组中 Char (*p2)[] = {“123”,”456”,”789”}; //编译器只分配4个字节,是一个指针,编译不通过、错误的方式 |
2、指针数组做函数参数退化
int printfArray(char *buf [30]); int printfArray(char *buf[]); int printfArray(char **buf); |
-
指针数组的两种用途
菜单
命令行
-
指针数组自我结束的三种方法
char* c_keyword[] = { "while", "case","static","do",'\0'}; char* c_keyword[] = {"while", "case","static","do",0}; char* c_keyword[] = {"while", "case","static","do",NULL}; |
6、当多维数组当做函数参数的话的时候会退化为指针
退化原因的本质是因为程序员眼中的二维内存,在物理内存上是线性存储 //总结:函数调用的时候,把数组首地址和有效数据长度传给被调用函数才是最正确的做法 |
一维数组做函数参数退化过程 //int a[10] -=-->int a[] ---->int *a //数组做函数形参的时候,如果在形参中定义int a[10]语句, //c/c++编译器会做优化,技术推演如下 //int a[10] -=-->int a[] ---->int *a
|
一维数组做函数参数退化过程 char buf[10][30])—》char buf[][30])----》char (*buf)[30])
|
int printfArray(char buf[10][30]); int printfArray(char buf[][30]); int printfArray(char (*buf)[30]); 这三者效果是一样的,也就验证了数组做函数参数退化为指针 |
第一种做法
int printfArray(int a[]) { int i = 0; printf("排序之前\n "); for (i=0; i<10; i++) { printf("%d ", a[i]); } return 0; } |
第二种写法 |
int printfArray04(int *a, int num) {
int i = 0; printf("排序之前\n "); for (i=0; i<num; i++) { printf("%d ", a[i]); } return 0; } |
1、 C语言中只会以机械式的值拷贝的方式传递参数(实参把值传给形参) |
int fun(char a[20], size_t b) |
原因1:高效 |
原因2: |
2、二维数组参数同样存在退化的问题 |
二维数组可以看做是一维数组 二维数组中的每个元素是一维数组 二维数组参数中第一维的参数可以省略 void f(int a[5]) ====》void f(int a[]); ===》 void f(int* a); void g(int a[3][3])====》 void g(int a[][3]); ====》 void g(int (*a)[3]); |
3、等价关系 |
数组参数 等效的指针参数
一维数组 char a[30] 指针 char* 指针数组 char *a[30] 指针的指针 char **a 二维数组 char a[10][30] 数组的指针 char(*a)[30] |
7、数组操作基础以及中括号本质
//c语言里面没有字符串这种类型。通过字符数组来模拟字符串
//C风格字符串是以零结尾的字符串
//操作数组的方法:下标法和指针法
void main() { int i = 0; char *p = NULL; //通过字符串初始化字符数组并且追加\0 char buf4[] = "abcd"; for (i=0; i<strlen(buf4); i++) { printf("%c", buf4[i]); //p[] } //[] *的本质到底是什么? //*p 是我们程序员手工的(显示)去利用间接赋值 //[] 只不过是,c/c++编译器帮我们做了一个*p的操作。。。。。。 // buf4[i]======> buf4[0+i] ====> *(buf4+i) //===*(buf4+i) --> bu4[i]; printf("\n"); p = buf4; for (i=0; i<strlen(buf4); i++) { printf("%c", *(p+i)); //*p } system("pause"); } |
void main12() { //字符数组初始化 //指定长度如果定义的长度剩余部分补充0 char buf1[100] = {'a', 'b', 'c'}; //不指定长度 char buf2[] = {'a', 'b', 'c'}; char buf3[] = {'a', 'b', 'c','\0'}; //通过字符串初始化字符数组并且追加\0 char buf4[] = "abcd"; printf("%s\n", buf4 ); printf("sizeof(buf4): %d\n ", sizeof(buf4)); //注意sizeof是对数据类型进行大小测量也就是数组类型包括了\0 printf("strlen(buf4): %d \n", strlen(buf4));//strlen是求字符串的长度不包括\0
system("pause"); } |