Fork me on GitHub

C数组和指针

摘要
数组和指针差别
指针的指针
指向数组的指针

数组和指针并不相同。

数组和指针的差别

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

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

什么时候数组和指针相同

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

例:

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

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

例:

1
2
3
4
5
6
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 的地址。
简单点就是:
&:取址。
*:取值。
指针的指针

指向数组的指针

1
2
3
4
5
6
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)); //使用指针表示

运行结果

1
2
3
qwert
terew
ytrytr

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

1
char (*p)[] = ch;

指针数组

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

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

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

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

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

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

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

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

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

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

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

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

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

1
2
3
4
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 a 和 char 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和指针(第二版)

+ +
-------------本文结束感谢您的阅读-------------

本文标题:C数组和指针

文章作者:史上最帅社会主义接班人

发布时间:2018年05月19日 - 21:05

最后更新:2018年05月20日 - 21:05

原始链接:https://www.buguagaoshu.com/2018/05/19/C数组和指针/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

打赏链接还是要有的,万一真的有人打赏呢