是否允许C编译器优化对未分配内存的访问?
考虑下面的代码是否允许C编译器优化对未分配内存的访问?,c,C,考虑下面的代码 int main() { int* p = (int*)0xABCDEFAB; int a; a = *p; /* do something with a */ return 0; } 是否允许编译器优化对p所指内存位置的访问?由于它未分配(因此其内容未定义),并且内存访问不是程序的可观察行为,因此应该允许它,但另一方面,p可能指向内存映射的I/O 从C标准的角度来看,正式答案是什么 注意:如果p被定义为volatile int*,编译器当然不应该优化
int main()
{
int* p = (int*)0xABCDEFAB;
int a;
a = *p;
/* do something with a */
return 0;
}
是否允许编译器优化对p
所指内存位置的访问?由于它未分配(因此其内容未定义),并且内存访问不是程序的可观察行为,因此应该允许它,但另一方面,p可能指向内存映射的I/O
从C标准的角度来看,正式答案是什么
注意:如果p被定义为volatile int*,编译器当然不应该优化访问,但它不是volatile。来自
整数可以转换为任何指针类型。除了前面指定的[当整数的计算结果为0时]
结果是定义了实现,可能未正确对齐,可能未指向
引用类型的实体,并且可能是陷阱表示形式
基本上,C标准不处理手工编制的地址,只处理从对象获取的地址
如果在您的实现中,
0xabcdef
结果是未对齐的,那么引用它将是未定义的行为1(并且编译器可以忽略加载)
如果对齐了0xabcdef
,指针p
可能不会指向地址0xabcdef
或类型为int
的对象,引用该对象将是特定于实现的2。在这种情况下,编译器不能直接忽略加载,但由于总体行为是特定于实现的,最终结果可能微不足道,可以进行优化 例如,假设我们有一个编译器,其中以ab开头的整数都是 映射到体系结构地址
0xffff
和目标体系结构的地址,该地址始终读取0(在任何系统中)。编译器可以直接优化加载和归零
a
为了防止后一种情况,您需要使用volatile
简言之,本标准并未完全涵盖您的案例。
然而,有一个注释在读 用于将指针转换为整数或将整数转换为指针的映射函数旨在 与执行环境的寻址结构保持一致 这意味着,虽然标准不提供任何保证,但您可以期望编译器的行为合理。
此外,根据标准,应记录整数指针映射
一, 引用:
如果为指针指定了无效值,则一元*运算符的行为为 未定义 二, 引用附件J“实施特定行为”中的实施特定方面列表:
-将指针转换为整数或将指针转换为整数的结果。
-从一个 整数可以转换为任何指针类型。除了前面指定的[当整数的计算结果为0时] 结果是定义了实现,可能未正确对齐,可能未指向 引用类型的实体,并且可能是陷阱表示形式 基本上,C标准不处理手工编制的地址,只处理从对象获取的地址
如果在您的实现中,
0xabcdef
结果是未对齐的,那么引用它将是未定义的行为1(并且编译器可以忽略加载)
如果对齐了0xabcdef
,指针p
可能不会指向地址0xabcdef
或类型为int
的对象,引用该对象将是特定于实现的2。在这种情况下,编译器不能直接忽略加载,但由于总体行为是特定于实现的,最终结果可能微不足道,可以进行优化 例如,假设我们有一个编译器,其中以ab开头的整数都是 映射到体系结构地址
0xffff
和目标体系结构的地址,该地址始终读取0(在任何系统中)。编译器可以直接优化加载和归零
a
为了防止后一种情况,您需要使用volatile
简言之,本标准并未完全涵盖您的案例。
然而,有一个注释在读 用于将指针转换为整数或将整数转换为指针的映射函数旨在 与执行环境的寻址结构保持一致 这意味着,虽然标准不提供任何保证,但您可以期望编译器的行为合理。
此外,根据标准,应记录整数指针映射
一, 引用:
如果为指针指定了无效值,则一元*运算符的行为为 未定义 二, 引用附件J“实施特定行为”中的实施特定方面列表:
-将指针转换为整数或将指针转换为整数的结果。
-任何对象中字节的数量、顺序和编码C标准对程序的行为没有任何要求。编译器根本不知道这个内存没有分配,它可能是用于某些设备通信的内存(例如直接访问视频缓冲区),所以不允许编译器进行优化it@Lashanep不易挥发,这无关紧要吗?如果你的陈述是正确的,那么如何根据标准来证明它是正确的呢?程序的格式不正确。需要显式转换才能在整数和指针之间进行转换。编译器唯一不允许做的事情就是默默地接受它。C标准对程序的行为没有任何要求。编译器根本不知道这个内存没有分配,它可能是用于某些设备通信的内存(例如直接访问视频缓冲区),所以不允许编译器进行优化it@Lashanep不易挥发,这无关紧要吗?如果你的陈述是c