c - gcc 使用 source == dest 生成 memcpy?
问题描述
调用时memcpy()
,我尝试确保源/目标指针不重叠,因为规范说这是未定义的行为。但是,对于下面的简单示例,GCC 会生成一个memcpy()
with source == dest。
#include <stdio.h>
#include <string.h>
struct my_struct {
int a[5000] ;
} ;
int main(void)
{
struct my_struct a ;
struct my_struct *p_a = &a ;
memset( &a, 0, sizeof(a) ) ;
*p_a = a ;
printf("%d\n",p_a->a[10] );
return 0 ;
}
使用gcc -O0
,我的本地 GCC (5.4.0) 和 godbolt.org GCC x86-64 10.2 生成以下行*p_a = a
:
call memcpy
(我没有使用-O2
,因为这需要更复杂的示例来演示问题)
我问是因为我们有一个嵌入式系统,当memcpy()
源/目标重叠时会生成警告。但是,由于上面的示例,有些人希望在 source==dest 时关闭警告。什么是合理的?
解决方案
C 标准没有定义memcpy
源和目标重叠时的行为这一事实并不意味着 C 编译器不能要求、知道和依赖memcpy
它使用的特定对象在源和目标重叠时的行为符合预期的事实。
在这种情况下,唯一的要求memcpy
(除了 C 标准的要求)是它在源和目标相同的情况下工作。如果 C 编译器需要memcpy
它使用的属性,那么根据 C 标准这是可以的——C 实现可能对其软件有任何内部要求。C 标准仅管理软件的外部行为,而不管理软件内部的工作方式。
这是一个相当温和的要求,不定义源和目标重叠时的行为的原因是memcpy
,在写入重叠目标的过程中,可能的各种实现可能会在读取源之前更改部分源。但是,当源和目标相同时,不会发生这种情况,至少在memcpy
. 所以这是一个很容易满足的要求。
编译器memcpy
生成的代码效率低下,因为它没有净效应,但这无关紧要,因为代码是在禁用优化的情况下生成的。
推荐阅读
- mysql - Sails 1.0 (Waterline ORM) - MySQL 属性 Date
- spring-webflux - 在 Web Flux 中使用格式化程序
- c++ - clang-tidy - 忽略第三方标头代码
- raspberry-pi - Ublox NEO-M6 和 Raspberry Pi3
- android - 如何在 react-native-charts-wrapper 中的图表上设置点选择?
- python - 在 django 中集成“直接消息”功能的最佳方法是什么?
- git - 在 Git 中以交互方式变基时的“标签”是什么
- binary - 符号大小和二的恭维
- bash - jq如何获取对象中的最后一个条目
- botium-box - “botium-cli 仿真器控制台”失败并显示“错误:缺少功能‘CONTAINERMODE’或‘BOTIUMGRIDURL’”