gpt4 book ai didi

c - char[] + memcpy() 是否违反严格别名?

转载 作者:行者123 更新时间:2023-11-30 15:01:18 24 4
gpt4 key购买 nike

我在结构中使用 char 数组来保存一些通用数据,如下所示(输入类型可能是未知大小的结构,因此我不能只使用 union ;这代码被大大简化):

typedef struct {
char buf[256];
} data;

void data_set_int(data *d, int a) {
memcpy(d->buf, &a, sizeof(a));
}

int data_get_int(data *d) {
int ret;
memcpy(&ret, d->buf, sizeof(ret));
return ret;
}

void data_set_float(data *d, float a) {
memcpy(d->buf, &a, sizeof(a));
}

float data_get_float(data *d) {
float ret;
memcpy(&ret, d->buf, sizeof(ret));
return ret;
}

int main(void) {
data d;

data_set_int(&d, 3);
int int_result = data_get_int(&d);

data_set_float(&d, 10.0f);
float float_result = data_get_float(&d);

return 0;
}

如果我从未尝试编写 float 然后将数据读取为 int 或反之亦然,那么这段代码在 C(99) 中定义良好吗?

使用 GCC 编译不会产生任何警告,并且运行代码会给出预期的行为(int_result == 3float_result == 10.0f)。将 memcpy 更改为正常的指针取消引用 (int ret = *(int *)d->buf) 也可以正常工作,不会出现警告。

我读过的所有关于严格别名的资料都说你可以将任何类型读取为 char * (所以我认为这意味着 set 应该没问题) ,但您不能将 char * 读取为任何其他类型(不太确定 get 是否正常)。我是否误解了规则?

最佳答案

在 C89 下,memcpy 的行为类似于使用 unsigned char* 读取源的每个字节,并使用 unsigned char* 写入目标的每个字节>;由于字符指针可用于访问其他任何内容,因此 memcpy 可以通用用于数据转换。

C99 向 memcpy 添加了一些新限制,仍然允许在目标对象具有已声明类型或所有非字符指针的有效类型的情况下使用它用于读取目标对象的类型与源的有效类型一致,但使没有声明类型的对象处于只能使用源类型读取的状态。我认为 C11 并未以任何有意义的方式放松这些限制。

您的代码不应受到 memcpy 规则的影响,因为每个 memcpy 操作要么写入具有声明类型的对象,要么写入仅通过 memcpy 写入具有声明类型的对象的红色存储。当代码需要就地更新对象而不知道接下来要读取的类型时,C99 的 memcpy 规则的主要问题情况就会发生。

例如,在 intlong 都具有相同 32 位表示的系统上,应该可以编写一个函数来将数据加载到任一int[]long[] ,而无需知道它正在接收哪种类型的指针(两种情况下机器操作的顺序都是相同的)。如果代码将一些数据读取到临时 int[] 中,然后使用 memcpy 将其移动到最终目标,则标准将保证该序列在目标位置正常工作是 int[]long[] 类型的实际声明对象,或者它是分配的存储区域,将被读取为 int[],但如果它是接下来将被读取为 long 的已分配存储区域,则不能保证正常工作。

关于c - char[] + memcpy() 是否违反严格别名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41517835/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com