double fun(int i)
{
volatile double d[1] = {3.14};
volatile long int a[2];
a[i] = 1073741824;
return d[0];
}
有趣(0)➙3.14
有趣(1)➙3.14
有趣(2)➙3.1399998664856
有趣(3)➙2.00000061035156
有趣(4)➙3.14,然后分段错误
有人可以向我解释在这个例子中发生了什么以及为什么在调用func(2)时不会出现segfault? 为什么返回值不总是3.14?
答案 0 :(得分:5)
您声明一个包含2个条目的数组:
volatile long int a[2];
然后使用索引访问此数组:
a[i] = 1073741824;
由于C中的数组索引从0开始,任何大于1的索引都会产生未定义的行为。
在您的程序中,您正在使用索引i=2
,i=3
和i=4
调用该函数。
这些函数调用中的每一个都独立地产生未定义的行为。
未定义的行为意味着任何都可能发生。
您只在fun(4)
遇到分段错误这一事实仅仅是巧合。
免责声明:以下分析并不意味着在每个平台上,甚至在每次执行时都会出现相同的行为;它只是为了解释观察到的“奇数”返回值。
1073741824
的4字节十六进制值为0x40000000
3.14
的8字节十六进制值为0x40091EB851EB851F
(符合IEEE 754)0x40000000
写入a[2]
,您已覆盖d[0]
的8字节值中的4个最低有效字节(不会导致分段错误),从而将其更改为{ {1}}到0x40091EB851EB851F
,代表({75})浮点值0x40091EB840000000
3.1399998664856
写入0x40000000
,您已覆盖a[3]
的8字节值中的4个最重要字节(不会导致分段错误),从而将其更改为{ {1}}到d[0]
,代表({75})浮点值0x40091EB851EB851F