搬运1:关于对C语言中数组名取地址加减等操作的一点探究

时间:2021-12-03 07:34:00

对于数组名取地址强制转换的操作

偶然在晚上学了C语言指针后网页闲逛找题时,被一个数组名取地址搞糊涂了,在自己试验加探索后我稍微悟了一点东西。

代码如下:

#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int a[5] = { 1,2,3,4,5};
int* ptr = (int *)(&a + 1);
printf("%d,%d", *(a + 1), *(ptr - 1));
return 0;
}

这里设置了一个长度为5的数组,之后定义一个int类型的指针将对a的首地址求地址后加1然后再次强制转换成int类型的指针传递给ptr,我第一反应是a不就是代表指向首个元素的地址吗,为什么还要对它求地址另外求完地址之后+1操作再次把一个指向地址转换成指针类型给了ptr,这让我十分费解,我们先来看输出结果

输出案例1:

搬运1:关于对C语言中数组名取地址加减等操作的一点探究

之后我首先删除了(int *)试着查看结果:

	int* ptr = (&a + 1);

输出案例2:

搬运1:关于对C语言中数组名取地址加减等操作的一点探究

发现输出案例是没有变化了,所以说明这里强制转化实质上是没有起到任何效果的,但是对于指针的强制类型转换真的没有用吗?

探究强制转换

无论任何类型的指针都是占四个字节的,只不过指向的值的类型不同从而定义为不同的类型,所以这里的强制类型转化应该是为了抱着把数组名这个指针转化成int类型的指针。所以我又做了如下测试:

把数组a改成char类型

搬运1:关于对C语言中数组名取地址加减等操作的一点探究

(忽略那个没有刷新的缺少;分号)对于int的初始化使用char,会产生警告,所以这里强制转化我们是可以理解了。

探究对于数组名取地址

在网上翻阅其他博客后查阅得知,因为数组名是一个右值,而求址运算符&是需要有具体的内存空间,也就是变量

//另外我们需要明确数组名和指针有一个区别是:数组名是符号地址常量,只是代表了数组中首个元素的地址,而没有明确的内存空间去存储它(也就是为什么不把数组名直接称为指针),在编译时求值并存在编译器的符号表里面,其值就是个内存地址,而指针是指向某一片区域,并且有一个内存空间存储这个指针,因此有了二级指针三级指针的概念,而对于数组求地址还是它自己。

所以对于数组名取地址在早期的编译器当中是非法的,但是现在是未定义的,因此我们改变代码后查看结果:

int* ptr = (int *)(a + 1);

输出案例3:

搬运1:关于对C语言中数组名取地址加减等操作的一点探究

这里去掉&后得到的答案却变了,这是因为含&时,对于一个t类型的地址a将进行a+长度**运算数*sizeof(t) ,而这里不含&时,将只是简单的对于地址进行加减 运算数 操作。

加减过程

如上所说的运算过程,这里我们只需要注意一个点也就是含&时的运算

这里我们对代码进行修改供参考。

数组a的长度为5时

搬运1:关于对C语言中数组名取地址加减等操作的一点探究

数组a的长度为4时

搬运1:关于对C语言中数组名取地址加减等操作的一点探究

(可以看到这里地址的加减是和长度有关的)

至于和操作数和sizeof()的关系各位可以下去试一试。

------男儿何不带吴钩,收取关山五十州。

by二十岁的编程男神王大爷