我正在创建一个int数组,然后欺骗c,使其相信它是一个短值数组。我知道这不是好习惯,但我只是想了解为什么这不起作用。这不应该改变arr [3]的值吗?
#include <stdio.h>
int main() {
printf("Hello, World!\n");
int arr[5];
arr[0] = 0; arr[1] = 0; arr[2] = 0; arr[4] = 0;
arr[3] = 128;
((short*)arr)[6] = 128; // Shouldn't this change arr[3] ? as 6,7 indices in the arr of short would compromise of arr[3] in arr of ints?
int i = 0;
for (i = 0; i < 5; i++){
printf("%d\n", arr[i]);
}
return 0;
}
PS:这是一个更深入的澄清: 当我将int数组转换为一个短数组时,它似乎变成了一个包含10个短元素(不是5个)的数组。所以当我改变arr [6]时,我只改变了int arr [3]的前16位。所以arr [3]仍然应该改变,并不是我再次将它改为128并且没有看到变化。
澄清:此代码仅用于实验原因!我只是学习指针如何工作,我认为这不是很好的做法。
答案 0 :(得分:2)
您的代码具有未定义的行为,因为您通过指向其他类型的指针编写具有声明类型的数据,并且不同的类型不是char
。
int arr[5];
/* ... */
((short*)arr)[6] = /* ANYTHING */;
编译器有权生成根本不包含对((short*)arr)[6]
的写入的机器代码,这很可能适用于现代编译器。它还有权删除main
的整个主体,理论上该程序的所有可能执行都会引发未定义的行为,因此程序将永远不会被运行。
(有人说,当你编写一个具有未定义行为的程序时,C编译器有权让恶魔飞出你的鼻子,但作为一个退休的编译器开发人员,我可以向你保证,大多数C编译器实际上都不能做这一点。)
答案 1 :(得分:0)
它正在更改arr[3]
,但是您将其设置为128,因此您不会注意到更改。将行更改为:
((short*)arr)[6] = 72;
你应该看到以下输出:
如果您是C新手,还需要清理几件事。您可以通过执行以下操作将数组初始化为零。
...
int arr[5] = { 0 };
arr[3] = 128;
...
希望这有帮助!
答案 2 :(得分:0)
您考虑过endianness吗?
编辑:现在增加更多清晰度......
正如其他人在评论中提到的那样,这绝对是 undefined 行为!这不仅仅是&#34;不是良好的做法&#34;,它只是不做!
Pointers on C是一本优秀的书,涵盖了你想要了解的关于指针的所有内容。它已过时但仍然非常相关。你可以在网上找到大部分的信息,但我还没有看到很多关于指针的书和这本书完全一样。
虽然听起来像是在试验,但可能是课堂的一部分。所以,这段代码有很多问题:
请记住,即使C今天被认为是一种非常低级的语言,它仍然是一种高级编程语言,可以提供许多关键的抽象。
现在,再看看你的宣言。
int arr[5];
您已将5个整体分组在一起,并通过名为arr的公共变量进行访问。根据标准,该数组是每个元素至少 2个字节的5个元素,其基址为&arr[0]
。因此,您无法保证 int 是2个字节,或4个字节或其他。同样,由于 short 被标准定义为至少2个字节。但是, short 不 int ,即使它们具有相同的字节宽度!请记住,C是强类型的。
现在,看起来您正在一台机器上运行,其中 short 是2个字节而 ints 是4个字节。这就是字节序问题发挥作用的地方:你最重要的位在哪里?您最重要的字节在哪里?
通过将 arr 的地址转换为短指针,首先会破坏类型和内存访问模型。然后,您想要从 arr 的偏移量中访问第6个元素。但是,您不能相对于您声明 arr 的 int 进行访问,而是通过指向的短指针进行访问与 arr 的地址相同!
以下操作不相同!它也属于 undefined的范畴 - 不要这样做!
int foo;
int pfooInt;
short bar;
short * pfooShort;
bar = (short) foo;
pfooShort = (short*)&foo;
pfooInt = &foo;
bar = *pfooShort;
pfooShort = (short*)pfooInt[0];
另一件需要澄清的事情是:
int arr[5];
((short *)arr)[6] ...
这不会将5个元素的int数组转换为包含10个元素的短数组。 arr 仍然是一个包含5个元素的int数组。您刚刚破解了访问方法,并试图以未定义的方式修改内存。你做的是告诉编译器&#34;忽略我之前告诉你的关于 arr 的内容,将 arr 视为该语句生命周期的短指针并访问/修改相对于此指针的第6个短。&#34;