【发布时间】:2020-03-24 10:31:12
【问题描述】:
我只是在测试我对指针的理解,同时我这样做了,
好吧,这就是我的想法。
所有指向任何类型的指针都保存地址,对吧?
说我声明char *a, b = 'f';
a = &b ;
因此,当我尝试通过指向 char 类型的指针访问 b 的内容时,这没关系。
但是,如果我将 int 数据类型的地址存储在 char 类型的指针中会怎样(尽管我收到警告:来自不兼容指针类型 [-Wincompatible-pointer-types] 的赋值,但我没有做错,对吧?我仍在存储一些内存的地址。)
int main(){
// int type of one byte
int a, i ;
char *b;
for(i = -256 ;i < 257; ++i){
a = i;
b = &a;
printf("for i = %d, value stored in first byte of a = %d\n",i ,*b);
}
return 0;
}
现在我认为它只允许读取分配给 a 的 4 个字节中的第一个字节,因为我正在通过指向 char 的指针进行访问类型,我希望存储高达 255 的值,超出这将是一种溢出。
但发生了一些不同的事情,我只能存储 127 到 -128 哇!!。你看到它是一个字节大小的 int 类型吗。你可以运行代码来查看。
现在假设 int 类型的大小为一字节
当 a = 256 时,读取的值为 0,这是预期的,因为 0001 0000 0000 它将只读取第一个字节。
输出是可预测的,直到我们达到 a = 127,它存储为 0111 1111(从 int 类型的角度来看是正值)
当 a = 128 时,输出为 -128 ,存储 1000 0000 (实际上是 -128)
同样可以解释其他输出
所以输出可以通过假设 int 类型的大小为一个字节来解释,为什么 printf 这样做而不是抛出错误。
那么 printf 到底做了什么?
谢谢各位大人 ;)
【问题讨论】:
-
请注意,您的代码也依赖于字节序
-
a = &b;(或后面程序中的b = &a;)是违反约束的——这是不允许的。您可以使用-Werror编译器标志来获取错误消息。 -
如果您的第一段使用与程序相同的变量名,则不会那么混乱
-
@M.M:允许违反约束。 C 标准需要 C 实现来诊断它们。它不需要 C 实现来禁止它们,并且确实允许 C 实现成功地转换包含违反约束的程序。
-
@EricPostpischil 标准不要求实现来翻译违反约束的程序,因此我将其描述为“不允许”。在您的术语中,几乎所有内容都是“允许的”(因为它是正确的,或者因为标准对包含违反约束或其他未定义行为的程序的行为没有要求),因此这样的术语是无用的
标签: c printf integer-overflow