风吹来了 发表于 2020-3-27 21:33:51

数组和指针

本帖最后由 风吹来了 于 2020-3-27 21:35 编辑

这段时间在学数组和指针,做了一些碎片化的笔记跟大家分享一下:

和普通变量一样,应该使用声明来初始化const数据,因为一旦声明为const,便不能再给它赋值。当初始化列表中的值少于数组元素个数时,编译器会把剩余的元素都初始化为0。如果初始化数组时省略方括号中的数字,编译器会根据初始化列表中的项数来确定数组的大小。可以用sizeof运算符计算出整个数组的大小。例如:int days = {1, 2};printf(“%zd”,sizeof days);就可以打印出days数组的占空间大小(以字节为单位)。 利用初始化器可以初始化指定的数组元素。可以在初始化列表中使用带方括号的下标指明待初始化的元素:int arr= { = 212}; // 把arr初始化为212对于一般的初始化,在初始化一个元素后,未初始化的元素都会被设置为0。 如果指定初始化器后面有更多的值,如该例中的初始化列表中的片段: = 31,30,31,那么后面这些值将被用于初始化指定元素后面的元素。如果再次初始化指定的元素,那么最后的初始化将会取代之前的初始化。 如果未指定元素大小编译器会把数组的大小设置为足够装得下初始化的值。 C不允许把数组作为一个单元赋给另一个数组,除初始化以外也不允许使用花括号列表的形式赋值。在计算机内部,数组中的元素是按顺序排列的。数组表示法其实是在变相的使用指针。数组名是数组首元素的地址。在C中,指针加1指的是增加一个存储单元。指针表示法直接表示了地址,如果需要这个地址上存储的值,则需要用*解引用;而数组表示法则是直接表示了值,如果需要这个值的地址,则需要用&地址运算符。只有在函数原型或函数定义头中,才可以用int ar[]代替int * ar。C保证在给数组分配空间时,指向数组后面第一个位置的指针仍是有效的指针。但并未对储存在该位置上的值做任何保证。不过嘛,嘿嘿,我们可以修改这个位置上的值。%td转换说明打印地址的差值.指针是C语言中广泛使用的一种数据类型。无论如何,使用指针时一定要注意,不要解引用未初始化的指针! const double * pd = rates; 指向const的指针不能用于改变值。但是可以改变指向const的指针本身的值,也就是说可以改变这个指针储存的地址。首先,把const数据或非const数据的地址初始化为指向const的指针或为其赋值是合法的。然而,只能把非const数据的地址赋给普通指针。因此,对函数的形参使用const不仅能保护数据,还能让函数处理const数组。可以声明并初始化一个不能指向别处的指针:double * const pc = rates;在创建指针时还可以使用const两次,该指针既不能更改它所指向的地址,也不能修改指向地址上的值:const double * const pc = rates; int (* pz); // pz指向一个内含两个int类型值的数组int * pax; // pax是一个内含两个指针元素的数组,每个元素都指向int的指针由于[]优先级高,先与pax结合,所以pax成为一个内含两个元素的数组。然后*表示pax数组内含两个指针。最后,int表示pax数组中的指针都指向int类型的值。因此,这行代码声明了两个指向int的指针。而前面有圆括号的版本,*先与pz结合,因此声明的是一个指向数组(内含两个int类型的值)的指针。即使pz是一个指针,不是数组名,也可以使用pz这样的写法。可以用数组表示法或指针表示法来表示一个数组元素,既可以使用数组名,也可以使用指针名: zippo == *(*(zippo + m) + n) pz == *(*(pz + m) + n) 指针之间的赋值比数值类型之间的赋值要严格。例如,不用类型转换就可以把int类型的值赋给double类型的变量,但是两个类型的指针不能这样做。 int **p2; // 一个指向指针的指针标准规定了通过非const指针更改const数据是未定义的。所以不要将const指针赋给非const指针!!!!!!!!更不要用非const指针更改const类型的数据!!!! 不能在声明中初始化变长数组。变长数组不能改变大小变长数组中的“变”不是指可以修改已创建数组的大小。一旦创建了变长数组,它的大小则保持不变。这里的“变”指的是:在创建数组时,可以使用变量指定数组的维度。C99/C11标准规定,可以省略原型中的形参名,但是在这种情况下,必须用星号来代替省略的维度: int sum2d(int, int, int ar[*][*]); // ar是一个变长数组(VLA),省略了维度形参名 需要注意的是,在函数定义的形参列表中声明的变长数组并未实际创建数组。和传统的语法类似,变长数组名实际上是一个指针。 字面量是除符号常量外的常量。对于数组,复合字面量类似数组初始化列表,前面是用括号括起来的类型名。例如,下面是一个普通的数组声明: int diva = {10, 20}; 下面的复合字面量创建了一个和diva数组相同的匿名数组,也有两个int类型的值: (int ){10, 20} // 复合字面量注意,去掉声明中的数组名,留下的int 即是复合字面量的类型名。 初始化有数组名的数组时可以省略数组大小,复合字面量也可以省略大小,编译器会自动计算当前的元素个数:(int[]){50, 20, 90} // 内含3个元素的复合字面量因为复合字面量是匿名的,所以不能先创建然后再使用它,必须在创建的同时使用它。使用指针记录地址就是一种用法。也就是说,可以这样用: int * pt1; pt1 = (int ) {10, 20};与有数组名的数组类似,复合字面量的类型名也代表首元素的地址,所以可以把它赋给指向int的指针。还可以把复合字面量作为实际参数传递给带有匹配形式参数的函数: int sum(const int ar[], int n); ... int total3; total3 = sum((int []){4,4,4,5,5,5}, 6);这里,第1个实参是内含6个int类型值的数组,和数组名类似,这同时也是该数组首元素的地址。这种用法的好处是,把信息传入函数前不必先创建数组。

ET也想不到 发表于 2020-4-2 17:51:36

马克一下!
页: [1]
查看完整版本: 数组和指针