C数组和指针

C数组和指针

陕西颜值扛把子 1,224 2020-04-23

数组和指针的差别

数组指针
保存数据保存数据地址
直接访问数据a[i]只是简单地以a+i为地址取得数据间接访问数据,首先取得指针内容,把它作为地址,然后从这个地址提取数据。如果一个直接下标[i],就把指针内容加上i作为地址,从中提取数据
通常用于储存固定数目且数据类型相同的元素通常用于动态结构
隐式分配和删除相关函数为malloc(),free()
自身即为数据名通常指向匿名数据

数组和指针都可以在它们定义中使用字符串常量进行初始化,尽管看上去一样,但是底层机制却不相同
定义指针时,编译器并部位指针所指向的对象分配控件,它只是分配指针本身的空间,除非在定义的同时赋值给指针一个字符串常量进行初始化。
在ANSI C中,初始化指针所创建的字符串常量通常被定义为只读。

什么时候数组和指针相同

规则一:表达式中的数组名就是指针

例:

int a[10], *p, i = 2;
p = a;
p[i];

规则2:C语言把数组下标作为偏移量

例:

int a[10], *p, i = 2;
p = a;
for(i = 0;i < 10;i++)
{
    *(p+i) = 0;  //与a[i] = 0;相同
}

出自:C专家编程P204

规则三:最为函数参数的数组名等同于指针

这个比较简单就不多解释了

指针的指针

让我们暂时忘掉那些关于指针的各种类比。指针实际上存放的是内存的地址。
& 符号的意思是取地址,也就是返回一个对象在内存中的地址。
*符号的意思是取得一个指针所指向的对象。 也就是如果一个指针保存着一个内存地址,那么它就返回在那个地址的对象。
所以当你这么写时 *ipp = ip2,实际上是把 ipp 存的地址所对应的对象,也就是 ip1 取到,然后把 ip2 存的值赋值给 ip1,也就是 j 的地址。

简单点就是:
&:取址。
*:取值。

czhizheng1.jpg

指向数组的指针

char (*A)[10];  //指向一个内含两个char类型的值的数组
char ch[3][10] = {"qwert","terew","ytrytr"};
A = ch;      //使A指向ch的第一行
printf("%s\n", A);
printf("%s\n", A[1]);
printf("%s", *(A+2));  //使用指针表示

运行结果

qwert
terew
ytrytr

警告
如果打算在指针上执行任何指针运算,应避免这种类型的声明

char (*p)[] = ch;

指针数组

指针变量和其它变量很相似,你可以声明一个指针数组来取得一个类似二维数组的效果

// A是一个内含n个指针元素的数组,每个元素都指向char类型的指针
char *A[n];

由于[ ] 的优先级高于* 所以a先和 [ ]结合,他还是一个数组,数组中的元素才是char * ,前面讲到char * 是一个变量,保存的地址

用于实现多维数组的指针数组有多种名字,如向量,用于激活一个在词法上封闭过程的活动记录,作为一个静态结点后跟一个链表的代替方案
下图演示了这种结构

19zj2.JPG

这种数组必须用指向为字符串而分配内存的指针进行初始化,可以在编译时用一个常量初始值,亦可以用以下代码进行初始化

for(j = 0;i <= 4;j++)
    pea[j] = malloc(6);

另一种方法是一次性使用malloc()分配整个X*Y个数据的数组

malloc(row_size*column_size*sizeof(char));

char *A[]和char **A区别

在C中,数组和指针通常是可以互换的,但是有一些区别:

1.用char * A [],你不能给A赋值,只能赋A[x];
使用char ** A,您可以将值赋给AA[x]

2.用char * A[],你可以初始化一个数组(例如char * A [] = {“foo”,“bar”})并使用sizeof(A)来获取大小(64位机器,上面的例子给你16,因为它是两个char *的数组;用char ** Asizeof(A)总是返回一个指针的大小(在64位机器上,8)。

可以写成P[][]类型的几种定义

int p[23][12];
int *p[23];
int **p;
int (*p)[12]

区别

1.当char []作为函数的参数时, 表示 char * 当作为函数的参数传入时, 实际上是拷贝了数组的第一个元素的地址,

所以 void test (char a[]) 等同于 void test ( char * a )

char x[10]; 然后调用 test(x) 则等同于把 x 的第一个元素的地址赋予给参数 a .

2.char * achar a[]
相同点 : a都是指针, 指向char类型.
不同点 : char a[] 把内容存在stack .
char *a 则把指针存在stack,把内容存在constants.

3.char * a[10]char a[10][20]
相同点 : a 都是2级指针, *a 表示一级指针, **a 表示内存中存储的内容.

不同点 : char * a[10], 数组由char * 类型的指针组成;

char a [10][20] 表示一位放10个元素, 二维放20个元素, 值存放地是一块连续的内存区域, 没有指针.

4.小窍门 : []*的数量对应, 如 char a[][]的指针层数是2, 相当于char **a; char *a[]也是如此, 两层指针. 迷糊的时候数数到底有几个*几个[], 就知道什么情况下存储的是内容还是地址了? 如char a[][] 的情况里面: &a, a, *a 都是地址, **a 是内容.

参考资料

C专家编程

C和指针(第二版)