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
fun(4) ➙ 3.14,然后出现段错误
有人可以向我解释一下这个例子中发生了什么以及为什么在调用 func(2) 时没有出现段错误吗? 为什么返回值不总是 3.14?
最佳答案
您声明一个包含 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 个最低有效字节
code> (不会导致段错误),从而将其从0x40091EB851EB851F
更改为0x40091EB840000000
,它代表3.1399998664856< 的 (IEEE 754) 浮点值
- 通过将
0x40000000
写入a[3]
,您已覆盖d[0] 的 8 字节值中的 4 个最高有效字节
code> (不会导致段错误),从而将其从0x40091EB851EB851F
更改为0x4000000051EB851F
,它代表2.0000006103516< 的 (IEEE 754) 浮点值
关于c - 为什么这个内存引用段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35148530/