《C专家编程》学习记录——指针和数组相同的地方
一、在普通的表达式中
普通的C语言表达式中,编译器把数组名数组名换成指向数组第一个元素的指针
先看一段简单的代码
char a[8];
a[3]=9;
3[a]=2;
printf("a[3] = %d\r\n", a[3]);
printf("3[a] = %d\r\n", 3[a]);
结果是:
a[3] = 2 3[a] = 2
原因:表达式中的数组名被编译器当做一个指向该数组第一个元素的指针(ANSI C标准),即在表达式中,指针和数组是可以互换的,因为他们在编译器里的最终形式都是指针,并且都可以进行取下标操作。就像加法一样,取下标操作符的操作数是可以交换的,所以表达式使用中,a[3]和3[a]两种形式都是正确的。(只为理解表达式中数组名被编译器当做指向数组第一个元素的指针,实际不用)。
二、数组做函数形参
编译器把数组名当做指向第一个元素的指针,且长度未知。
下面两种形式都可以,数组名都是当指针用。
void fun1(int *p); void fun2(int arr[]); int b[10] = {22,22,22,22,22,22,22,22,22,22}; int main(void) { int a[10] = {1,2,3,4,5,6,7,8,9,0}; fun2(a); } void fun1(int *p) { char i; p[1] = 20; *p = 10; for(i=0; i<10; i++)printf("%d ",p[i]);printf("\n"); p=b; for(i=0; i<10; i++)printf("%d ",p[i]);printf("\n"); } void fun2(int arr[]) { char i; arr[1] = 20; *arr = 10; for(i=0; i<10; i++)printf("%d ",arr[i]);printf("\n"); arr=b; for(i=0; i<10; i++)printf("%d ",arr[i]);printf("\n"); }
数组名是不可修改的左值,因此下面代码会编译错误,
int a[10] = {1,2,3,4,5,6,7,8,9,0}; int b[10] = {22,22,22,22,22,22,22,22,22,22}; a[1]=10; *a=20; a = b; //编译失败
这也证明函数参数是数组时,实际编译器是当指针处理的
另:结构体类型可以做函数参数,可以做函数返回值,可以做左值(用另一个结构体变量整体赋值)
另外:函数传参顺序,先右后左:
char a[12] = "hello,world"; char *p = a; printf("%x, %x, %x, %x", a, ++p, p++, p++);
结果:
54a632c0, 54a632c3, 54a632c1, 54a632c0
这是因printf是一个函数,计算参数时,是从右向左压栈的,所以最右边的p++先打印p的地址54a632c0,然后p++为54a632c1,再打印p的地址54a632c1,再p++为54a632c2,再++p为54a632c3