C语言基础之数组与指针的关系

    考虑以下程序段:

#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[]的大小,结果如下:

C语言基础之数组与指针的关系_第1张图片

    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);
}

C语言基础之数组与指针的关系_第2张图片

    我们发现,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");
}

C语言基础之数组与指针的关系_第3张图片

    说明函数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;
}

C语言基础之数组与指针的关系_第4张图片

    这说明,*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,结果如下:

C语言基础之数组与指针的关系_第5张图片

    ◆ 数组变量是const的指针,所以不能被赋值

int a[] <==> int* const a

 

你可能感兴趣的:(C语言基础之数组与指针的关系)