C语言之指针
以32为系统为例。
1、指针与地址
指针是一种变量,保存了所指向对象的地址。
1.1 定义
int i = 10;
int *p = &i; //定义了一个指针p,它指向一个int型的变量
&是地址运算符,*是间接引用运算符。
&i是取i在内存中的地址,*p = &i是将i的地址赋值给p,即p的值是i的地址。
1.2 引用
*p = 100 等价于 i = 100,即将i的值改成100
*p += 1 等价于 i += 1,即将i的值加1
*p++改变了p所指向的地址,此时p不再指向i的地址,而是指向i的地址+4的新地址。因为*(间接引用运算符)和++具有相同的优先级,且是从右到左的结合性,所以等价于*(p++)。p++是将指针加1,指向内存中下一个地址。由于这里的p是int型的,实际上是偏移了sizeof(int)=4个字节。例:
int i = 10;
int *p = &i;
*p++;
printf("i=%d, &i=%p, p=%p\n", i, &i, p);
打印结果:i=10, &i=0xbf99bd78, p=0xbf99bd7c
注意:绝对不能这么写*p++ = 111,因为这无意中非法改变了p下一个内存地址的值。
++*p 等价于 i的值加1
*++p 等价于 *p++
*p + 1 等价于 i 的值 加1
*(p + 1) 等价于*p++
2、指针和数组
int a[10];
int *p = &a[0]; //指针p指向数组a的首地址元素a[0]
或者int *p = a; //数组名所代表的就是该数组的第一个元素的地址,直接赋值给p
引用第i个元素:
a[i] 或者 *(a+i) 或者 *(p+i) 或者 p[i]
数组名和指针的差别:
指针是一个变量,可以赋值或者++,如p=a,p++
但数组名不行,不能这样:a=p, a++
指针的运算包括:
相同类型指针之间的赋值运算;指针同整数之间的加减法运算;指向相同数组中元素的两个指针的减法或比较运算;指针赋值为0,或指针与0之间的比较运算。
3、指针数组和指向指针的指针
指针数组:int *p[10]; //p是一个指针数组,具有10个元素,每个元素都是一个指向int型对象的指针。
指向指针的指针: int **p; //p是一个指针,指向一个int *型对象
4、二维数组
int a[10][20]; //二维数组,有10行,每行20列
int a[][20] = {........}; //二维数组,每行20列,行数会根据{...}内的值的个数自动计算,行数={...}中值的个数/20 + 1
二维数组必须要指定列数,行数可以不用指定。
二维数组作函数参数时,函数的声明方式可以是:
f (int a[10][20]) {...} 或者
f (int a[][20]) {...} 或者
f (int (*a)[20]) {...}
不能是f (int *a[20]) {...}
数组指针(行指针):char (*p)[20]是一个指针,指向具有20个char型元素的一维数组。
sizeof(p)=4,占用一个指针的存储空间
char a[10][20];
char (*p)[20];
p=a; //二维数组首地址给p,p指向a[0][0],即第0行的第0个元素
p++; //执行后,p指向a[1][0],即第1行的第0个元素
指针数组:char *p[20]是一个数组,具有20个元素,每个元素都是一个指向char型对象的指针
sizeof(p)=80,占用20个指针的存储空间
char a[10][20];
char *p[20];
p[0]=a[0]; //p[0]指向二维数组a的第0行
p[1]=a[2]; //p[1]指向二维数组a的第2行
两者的引用方式一样,都是:*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]
原因:[]的优先级高于*的优先级。
5、指向函数的指针
int (*f)(int i, int j) 定义了一个函数指针,这个函数有两个参数i和j,函数返回一个int型对象。
圆括号是必须的,否则就变成了int *f(int i, int j),这表示函数f返回一个int *型对象。
6、总结
char **x:x是指向指针的指针
char (*x)[10]:x是一个数组指针,指向一个具有10个元素的数组
char *x[10]:x是一个指针数组,每个元素都是一个指向char型对象的指针
char *x( ):x是一个函数,该函数返回一个指向char型对象的指针
char (*x)( ):x是一个函数指针,该函数返回一个char型对象
char (*(*x( ))[10 ])( ):定义了一个函数,该函数返回一个具有10个元素的数组指针,元素类型是函数x返回的指向char类型对象的指针
char (*(*x[10])())[2]:定义了一个数组,数组有两个元素,每个元素的类型是函数返回的指向一个10个元素的指针数组的指针