考虑以下程序段:
#define _CRT_SECURE_NO_WARNINGS
#include
void f(int a[], int len);
int main()
{
int a[] = { 1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55 };
printf("main()中的sizeof(a) = %d\n", sizeof(a));
f(a, sizeof(a) / sizeof(int));
return 0;
}
void f(int a[], int len)
{
printf("f()中的sizeof(a) = %d\n", sizeof(a));
}
我们希望分别得到main()和f()中a[]的大小,结果如下:
Visual Studio Enterprise 2019中的x64架构中,int* 的大小即为8,那么说明在main()函数调用f()时,仅仅是将数组a[]的首地址传给了函数f()。进一步地,考虑下面这段代码:
#define _CRT_SECURE_NO_WARNINGS
#include
void f(int a[], int len);
int main()
{
int a[] = { 1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55 };
printf("main()中的a = 0X%p\n", a);
f(a, sizeof(a) / sizeof(int));
return 0;
}
void f(int a[], int len)
{
printf("f()中的a = 0X%p\n", a);
}
我们发现,main()中int*的a和f()中int*的a指向的是同一块地址,那么我们就可以利用这样的性质直接修改main()中数组a[]的各个元素,代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include
void f(int a[], int len);
int main()
{
int a[] = { 1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55 };
f(a, sizeof(a) / sizeof(int));
printf("main()中的a[0] = %d\n", a[0]);
return 0;
}
void f(int a[], int len)
{
a[0] = 1000;
printf("f()修改a[0] = 1000\n");
}
说明函数void f(int a[], int len)中参数表中的a[]其实就是一个int* a,只是“样子”看上去像一个数组,那么我们就可以将函数f()中的参数进行修改:
#define _CRT_SECURE_NO_WARNINGS
#include
void f(int* a, int len);
int main()
{
int a[] = { 1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55 };
f(a, sizeof(a) / sizeof(int));
printf("main()中的a[0] = %d\n", a[0]);
return 0;
}
void f(int* a, int len)
{
a[0] = 1000;
printf("f()修改a[0] = 1000\n");
}
结果编译通过,并且运行结果正确,这说明数组和指针存在某种联系:
▲ 函数参数表中的数组实际上是指针
▲ sizeof(a) == sizeof(int*)
▲ 但是可以用数组的运算符[]进行运算
以下四种函数原型是等价的:
int sum(int* ar, int n);
int sum(int*, int);
int sum(int ar[], int n);
int sum(int [], int);
数组变量是特殊的指针:
◆ 数组变量本身表达地址,所以
▲ int a[10]; int* p = a; //无需用&取地址
▲ 但是数组的单元表达的是变量,需要用&取地址如:int* p = &a[1];
▲ a == &a[0]
◆ [] 运算符可以对数组做,也可以对指针做:
▲ p[0] <==> a[0]
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int a = 1;
int* p = &a;
printf("*p = %d\n", *p);
printf("p[0] = %d\n", p[0]);
return 0;
}
这说明,*p和p[0]的值是等于的,p[0]即编译器将int* p如果认为是一个数组的首地址,取出了第一个单元,但实际上并没有这样的一个“数组”。
◆ * 运算符可以对指针做,也可以对数组做:
#define _CRT_SECURE_NO_WARNINGS
#include
void f(int* a, int len);
int main()
{
int a[] = { 2,3,4,5,6 };
printf("修改前*a = %d\n", *a);
f(a, sizeof(a) / sizeof(a[0]));
printf("修改后*a = %d\n", *a);
return 0;
}
void f(int* a, int len)
{
*a = 23;
printf("f()修改了*a\n");
}
这样,在f()中对*a赋值*a = 23;将main()中的a[0]修改为23,结果如下:
◆ 数组变量是const的指针,所以不能被赋值
int a[] <==> int* const a