首页 > 代码库 > 数组与指针操作

数组与指针操作

一,数组

1,const int array[5] = {0, 1, 2, 3, 4};

2,c99新特性,可以对指定的数组的某一个元素初始化。例如:int array[10] = {1, 3, [4] = 2, 6, 7, [1] = 32};如果多次对一个元素进行初始化,取最后一次的值。

3,c不支持把数组作为一个整体来赋值,也不支持用花括号括起来的列表形式进行赋值。

4,sizeof表达式被认为是一个整数常量。 5 * 5 - 1 就是整数常量表达式。

5,变长数组int array[n];变长数组是不能进行初始化的。

6,二维数组就是数组的数组。例如:float rain[5][12],首先,看中间黑体字部分,说明rain一个含有5个元素的数组,剩下的部分就是这5个元素中,每个元素的类型,所以rain是5个类型为float[12]的数组,rain的元素是12个float型的数组。

 

二,指针和数组

7,数组名就是数组的地址,也就是数组首元素的地址,也就是指向该类型的元素的指针。

8,对指针加1,结果是对该指针增加了一个存储单元。该存储单元的大小取决于该指针的类型。4字节int=加4,8字节double = 加8。

9,c在符号操作的时候,优先级相同的两个符号的操作顺序是从右向左的。例如:*ptr++ 就是先加加,在取值。*和++的优先级是相同的。注意 int n = *ptr++;实际上n的是*ptr的值,因为是后缀操作,是当前表达式结束后,指针在进行++操作的。

10,arry[i] == *(arry + i);等价的关系。

11, 有效的求指针之间的差值的前提是参加运算的指针是指向同一个数组,指向两个不同数组的指针之间的差值的结果是不清楚的。

12,可以使用关系型运算符比较两个指针,前提两个指针具有相同的类型。

13,c能保证指向数组元素的指针和指向数组后的第一个地址的指针是有效的,其他的越界是不可预知的,但不能对指向数组后的第一个地址的指针进行取值操作。

14,声明指针的时候要进行初始化,没有指定的,就等于NULL,不能对未初始化的指针进行取值操作。当创建一个指针时,系统只分配了用来存储指针本身的内存空间,并不分配用来存储数据的内存空间。

 15,const int * ptr;是指向常量的指针,也就是指针指向的内容是不可以改变的,但是指针是可以指向其他的。例如:int array[2] = {0, 1}; cont int * ptr = array;

ptr --> array[0]; 不可以通过指针来修改array[0]的内容,但是ptr++是可以的,ptr++ 指向的就是array[1]。

16,常量的地址和非常量的地址赋给常量指针是合法的,但仅仅就是不能通过这个常量指针来修改指向的内容。非常量的数据地址才可以赋给普通指针。

17,const int * ptr; const 修饰的是 int * ptr;代表ptr指向的内存是不可以被修改的。

  int * const ptr; int *型的const ptr,const修饰的是ptr,代表着ptr是不可以指向其他的内存地址的。但是它指向的内存的值是可以被修改的。

18,int zippo[4][2];

(1)因为zippo是数组首元素的地址,所以zippo的值和&zippo[0]相同,另一方面,zippo[0]本身是包含两个整数的数组,因此zippo[0]的值同其首元素(一个整数)的地址&zippo[0][0]相同。简单地说,zippo[0]是一个整数大小对象的地址,而zippo是两个整数大小对象的地址。因为整数和两个整数组成的数组开始于同一个地址,因此zippo和zippo[0]具有相同的数值。

(2)对一个指针(也即地址)加1,会对原来的数值加上一个对应类型大小的数值。在这方面,zippo和zippo[0]是不一样的,zippo所指向对象的大小是两个int,而zippo[0]所指向对象的大小是一个int.因此zippo + 1和zippo[0] + 1的结果是不同。

(3)对一个指针(也即地址)取值(使用间接运算符*或者带有索引的[]运算符)得到的是该指针多指向对象的数值。因为,zippo[0]是其首元素zippo[0][0]的地址,所以*(zippo[0])代表存储在zippo[0][0]中的元素,即一个int数值。同样,*zippo代表首元素zippo[0]的值,但是zippo[0]本身就是一个int数的地址,即&zippo[0][0],因此*zippo是&zippo[0][0]。

19,二维数组 zippo + 1相当于纵向操作,*zippo + 1相当于横向操作。zippo[2][1] == *(*(zippo + 2) + 1);

20,[]的优先级高于*;

21,什么类型的数值就用什么类型的指针指向,指针赋值很严格。

22,之前说过const类型的指针可以指向非const类型的数值,但是这种情况是不合法的const int ** 指向int **;

23,指向多维数组的指针,如指向二维数组的指针 int (*ptr) [2]; ptr先与*结合,说明ptr是指向二维数组的指针。

int zippo[4][2] = {{2, 4}, {6, 8}, {1, 3}, {5, 7}};

int (*ptr)[2];

ptr = zippo;

zippo[m][n] == *(*(zippo + m) + n);

ptr[m][n] == *(*(ptr + m) + n);

24,编译器在处理数组的时候,是把数组转换成指针进行处理的。

25,函数的形参是多维数组的时候,如二维数组,可以这样写 void sum(int (*ptr)[4], int row);或者是void sum(int prt[][4], int row);二维数组的行是可以不写的,但是列是一定,因为编译器在处理二维数组的时候,转换成指针,要确定指向二维数组的指针指向的数组的元素的个数。

26,变长数组实在函数运行的时候,创建的数组。常规数组是在编译的时候就是创建了,因为能确定数组的大小。

27,复合文字,例如数组 int diva[2] = {10, 20}; 创建一个复合文字就是:(int [2]) {10, 20};也可以写成(int []){10, 20}; 可以用指针指向它:int *ptr = (int [2]) {10, 20};  (int [2]) {10,  20) 同数组名一样使用,就是数组地址,又是数组首元素的地址。

数组与指针操作