Learn And Life.

C指针

说起指针,不得不提下数组,因为两者在某些方面有相似之处,请看下面的代码:

1
2
extern int *x;
extern int y[];

数组在什么时候等同于指针呢?什么时候又不等同于指针呢?

1.数组和指针的访问方式

1
2
char a[9] = "abcdefgh";
char *p = "abcdefgh";

编译器编译的时候会生成一个符号表,这样a和p都在这个符号表里,每一个符号表,都有一个符号跟地址的对应关系,如下:
a–>9980
p–>4624

a–>9980–>+1–>+2–+3–>…->+i–>–>
编译器符号表地址9980
取i的值,将它与9980相加
取地址(9980+i)的内容

p–>4624–>5081–>data
编译器符号表地址 4624
取地址4624的内容,即5081
取地址5081的内容
也就是说,对于a而言,符号表的地址,即为数组a地址,然而对于p而言,符号表对应的地址,对应的是一个4字节的对象指针,而其内容存放的是一个地址,这个地址存储的数据即为指针所对应的数据。

2.使用指针来访问数组

1
2
char *p="abcdefgh";
c = p[i];

p–>4624–>5081 —|(5081+i)| —5081–>+1–>+2–>+3–>…–>+i–>–>
编译器符号表的p地址4624,提取存储于此处的指针5801
取下标偏移量,将其与指针的值相加,产生一个地址
访问这个地址,取得子符
同样也能访问到数组的内容d,只是访问的方式略有不同,首先进行间接引用,然后按照下标偏移量直接访问。

3.指针所引用的数据,其地址可以是不连续的,而数组,其地址是连续的,指针使用malloc()和 free()来管理内存,且只有字符串才可以初始化指针,其它类型均不可以直接赋值,且初始化之后,是只读的,不可以修改其值 .

4.数组和指针,有且只有作为函数的参数的时候,才是等同的

1
printf("array at location %x holds string %s", a, a);

这里数组既作为指针使用,也可以作为字符数组使用,只是因为printf是函数,参数中的数组和指针等同
又比如main函数

1
2
int main(char **argv,int argc);
int main(char *argv[], int argc);

是等同的.

5.应用
a. 二维数组

1
2
pea[i][j]
*(*(pea+i)+j)

等同,数组中单个元素的存储和引用实际上是以线性形式排列的内存重的,即以第一维作为组,第二位作为每个元素在组内的偏移量,这样线性排列.
b.函数指针

1
2
3
4
5
6
7
8
int (*paf())[20]{
int (*pear)[20];
pear = calloc(20, sizeof(int));
if(!pear) longjmp(error,1);
return pear;
}
int (result)[20];
result = paf();

c.Iliffe向量,即将一个二维数组,创建一个一维数组,数组中的元素是指向其它东西的指针

1
my_function(char **my_array);

my_array是一个二维数组,一个指向向量的指针数组