神奇的“数组转指针”

简介:

在论坛上看到类似下面的一段代码:

a.c:
int a[10]={1,2,3,4,5,6,7,8,9,0};
int *b = a;

b.c:
extern int *a;
extern int b[];

void main()
{
int x, y;
x = a[3];
y = b[3];
}

编译后运行,在main函数中,x和y分别等于什么呢?


用gdb对程序进行调试:
Breakpoint 1, main () at b.c:7
7 x = a[3];
(gdb) p a
$1 = (int *) 0x1
(gdb) p b
$2 = 0x804a068
(gdb) p *b
$3 = 134520896
(gdb) p **b
$4 = 1

可以看到,a的值是1,那么a[3]将是一个越界访问;**b的值才是1,那么b[3]应该还是个越界访问。

数组名被申明成指针、指针被申明成数组名,为什么会产生这样的结果呢?指针与数组名难道不能转换吗?

将数组名赋值给指针,这种转换是由编译器来完成的,编译器会生成一条“将数组名这个不变量的值赋给指针”的指令。然而,b.c在编译过程中,申明的指针a和数组名b是未决的符号(需要通过链接来解决)。所以,这里的类型转换不是编译器能干的事情。然后,在接下来的链接过程中,链接器也不干转换的事情,因为它只关心符号,不关心类型。于是:

在a.c中:
a被定义为数组名,a是一个不变量,没有自己的存储空间,这个不变量的值为134520896(见gdb的打印)。
b被定义为指针,b是一个变量,有自己的存储空间,这个存储空间里面存放的值是a的值,即134520896。

a.c与b.c编译生成的中间文件进行链接后,在b.c中(b.c生成的二进制文件中):
a被申明为指针,a是一个变量,有自己的存储空间,它的存储空间的地址是从a.c中链接过来的,是a.c中的a的值,即134520896。既然a的存储空间的地址是134520896,那么a的值自然就是1了。
b被申明为数组名,b是一个不变量,没有自己的存储空间,它的值是从a.c中链接过来的,是a.c中的b的存储空间的地址,即0x804a068。


可见,在链接过程中,因为数组名本身没有存储空间,所以链接时导出的是数组名所指代的数组的存储空间的地址;而指针本身是有存储空间的,所以链接时导出的是指针本身的地址。如果在这一过程中,数组名和指针发生转换,则会是错位的。


相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
目录
相关文章
|
1月前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
33 3
|
1月前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
38 2
|
1月前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
37 1
|
2月前
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。
|
2月前
|
存储
如何通过指针数组来实现二维数组?
介绍了二维数组和指针数组的概念及其区别,详细讲解了如何使用指针数组模拟二维数组,包括定义与分配内存、访问和赋值元素、以及正确释放内存的步骤,适用于需要动态处理二维数据的场景。
|
2月前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
2月前
魔法指针 之 二级指针 指针数组
魔法指针 之 二级指针 指针数组
20 1
|
2月前
|
存储
一篇文章了解区分指针数组,数组指针,函数指针,链表。
一篇文章了解区分指针数组,数组指针,函数指针,链表。
20 0
|
2月前
|
编译器 C语言
【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)
【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)
|
4月前
|
搜索推荐 C语言
指针与数组
指针与数组
59 9