前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >c语言进阶指南(10)(指针与数组)

c语言进阶指南(10)(指针与数组)

原创
作者头像
代码小豪
发布2024-06-13 19:46:09
550
发布2024-06-13 19:46:09
举报
文章被收录于专栏:C语言程序指南C语言程序指南

欢迎来到博主的专栏:C语言进阶指南

博主id:reverie_ly

指针的算术运算

指针可以进行加和减以及自加和自减算术运算。运算结果是

地址值加或减指针类型指向的元素的空间大小。

尝试运行以下代码

代码语言:c
复制
char c;
int i;
double d;

char* pc=&c;
int *pi=&i;
double* pd=&d;

printf("pc=%p\tpc+1=%p\n", pc, pc + 1);
printf("pc=%p\tpc+1=%p\n", pi, pi + 1);
printf("pc=%p\tpc+1=%p\n", pd, pd + 1);

%p是指针类型参数的转换声明。

我们可以发现pc+1与pc的地址差为1.

pi+1与pi的地址差为4

pd+1与pd的地址差为8

这是由于char*类型的指针指向的类型是char,所以加1是指向下一个char类型元素的空间大小(1字节)

以此类推

图中每一个空格表示一个内存中的字节

指针与数组

数组的元素都是在内存中连续排序的,那么也就是说可以用指针加减的方式来访问数组元素。

pi+1仍然是一个指针类型的值,所以想要访问元素或者对元素进行操作,那么就需要用到解引用操作符‘*’。

代码语言:c
复制
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9 ,10};
int* pi = arr;
for (i = 0; i < 10; i++) {
	printf("%d ", *(pi + i));
}
return 0;

可以发现一个很有意思的现象

*(arr+i)=arri

数组名

上面将数组名赋予了指针pi

代码语言:c
复制
int*pi=arr;

这是不是说明数组名本身是一个指针呢?我们可以在监视窗口中看到

arr作为数组时,是一个int[10的类型。这里在下例中可以看到

代码语言:c
复制
sizeof(arr);

sizeof的将会显示整个数组的大小。

但如果将arr作为指针使用时(arr+1),arr会被降级为int*类型(这一点在二维数组更为明显)

所以当我们将arr作为指针变量的值时,

赋予指针变量的是int*类型的arr中第一个元素的地址

数组arr降级的例子是

代码语言:c
复制
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9 ,10};
for (i = 0; i < 10; i++) {
	printf("%d ", *(arr + i));
}
return 0;

这里没有使用指针变量来进行操作,而是使用数组名来进行指针操作。可以发现这两个例子的结果都是一致的。

所以可以得出结论

当数组名作为指针层面的使用时,会发生类型降级,arr从int[]变为int*。

代码语言:c
复制
void print(int arr[])
{
	for (int i = 0; i < N; i++)
	{
		printf("%d", arr[i]);
	}
}
int main()
{
	int arr[N] = { 1,2,3,4,5,6,7,8,9,10 };
	print(arr);
	return 0;
}

这个print函数的参数是一个int[]类型的数组,所以可以将arr作为实参来传递。但是在这个函数中,数组名会被作为指针来操作(arri等价于(arr+i)).所以这个数组名被降级为int类型。

所以我们也可以一开始就让arr发生类型降级,直接将函数形参设定为int*类型的指针

代码语言:c
复制
void print(int* arr)//不再是int[]类型的arr。
{
	for (int i = 0; i < N; i++)
	{
		printf("%d", arr[i]);
	}
}
int main()
{
	int arr[N] = { 1,2,3,4,5,6,7,8,9,10 };
	print(arr);
	return 0;
}

这两个函数在使用时的效果完全一致。

敲重点:

1)int[]类型的数组名作为指针使用时,会被降级成int*类型的数组名

在大部分情况下,int[]类型与int的变量是可以互通的,但是为什么说int[]降级成int呢。

这两个类型的区别就在于声明阶段了

代码语言:c
复制
int arr[10]={1,2,3,4,5,6,7,8,9,10};//正确
int* pi = {1,2,3,4,5,6,7,8,9,10};//非法

int[]可以声明一个数组,而int*类型不能用于声明一个数组。

当数组名作为指针来使用时(比如作为函数的参数或者用数组名进行指针算术运算时),int[]和int*的变量是可以互通的。

比如

代码语言:c
复制
void print(int arr[])
{
	for (int i = 0; i < N; i++)
	{
		printf("%d", arr[i]);
	}
}
int main()
{
	int arr[N] = { 1,2,3,4,5,6,7,8,9,10 };
	int* pi = {1,2,3,4,5,6,7,8,9,10};
	print(pi);
	return 0;
}

这里是将int*的实参(pi)传递到int[]的形参(arr)中。

2)当数组名(arr)发生降级时,数组名将是首元素的地址、

代码语言:c
复制
int *pi=arr;

实际上pi的值是数组首元素的地址,(即&arr0,类型是int*)

数组下标与指针的关系

我们在前面的例子中已经很明显的发现了这么一个规律

我们知道将指针解引用得到就是该地址的数据。

所以(arr)=arr0(可以理解成(arr+0))。

由此可得*(arr+i)=arri。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 指针的算术运算
  • 指针与数组
    • 数组名
      • 数组下标与指针的关系
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档