gpt4 book ai didi

c - C 中的灵活数组和取消引用类型双关指针错误

转载 作者:行者123 更新时间:2023-12-01 23:54:04 25 4
gpt4 key购买 nike

当我尝试使用 gcc -O3 -Wall -Werror -std=c99 main.c 编译下面的代码时我收到类似 的错误消息“取消引用类型双关指针将破坏严格的别名规则”在#3,但不在#2 或#1。我可以取消引用类型双关语“char *”,但为什么我不能对灵活数组做同样的事情?

#include <stdlib.h>
#include <stdio.h>

struct Base {
void (*release) (struct Base *);
size_t sz;

char *str_foo;
char rest[];
};

struct Concrete {
char *str_bar;
};

void
Base_release(struct Base *base)
{
free(base);
}

struct Base *
Base_new(size_t sz_extra)
{
size_t sz = sizeof(struct Base) + sz_extra;
struct Base *base = (struct Base *)malloc(sz);
base->release = &Base_release;
base->sz = sz;

base->str_foo = "foo";
return base;
}

#define BASE_FREE(_obj) (_obj)->release(_obj)
#define BASE_CAST(_type, _obj) ((struct _type *)((_obj)->rest))
#define BASE_CAST_2(_type, _obj) ((struct _type *)((char *)(_obj)+sizeof(struct Base)))

struct Base *
Concrete_new()
{
struct Base *base = Base_new(sizeof(struct Concrete));
struct Concrete *concrete = BASE_CAST(Concrete, base);
concrete->str_bar = "bar";
return base;
}

int main(int argc, const char *argv[])
{
struct Base *instance = Concrete_new();
printf("Base str: %s\n", instance->str_foo);

// #1 - Legal
struct Concrete *cinstance = BASE_CAST(Concrete, instance);
printf("#1: Concrete str: %s\n", cinstance->str_bar);

// #2 - Legal
printf("#2: Concrete str: %s\n", BASE_CAST_2(Concrete, instance)->str_bar);

// #3 - Compile error
printf("#3: Concrete str: %s\n", BASE_CAST(Concrete, instance)->str_bar);

BASE_FREE(instance);

return 0;
}

编辑 1:
下面有更具体的例子显示问题:
struct s {                               
char a;
};
char *const a = malloc(sizeof(struct s));
char b[sizeof(struct s)];
((struct s *)((char *)a))->a = 5; // This is a valid case
((struct s *)(a))->a = 5; // OK
((struct s *)((char *)b))->a = 5; // ???

最佳答案

首先,它与灵活数组无关,而是与任何数组有关。您可以使用固定大小足够大的数组并看到相同的结果。

最明显的解决方法是您的 BASE_CAST_2 .另一个可能正在使用 offsetof而不是 sizeof ,特别是在结构尾部不灵活的情况下。

第一种和第三种情况之间的区别很棘手。它们都违反了严格的别名规则,但是当 gcc 无法确定左值的来源时,有时会允许这样做。但是,与 -Wstrict-alising=2在这两种情况下它都会发出警告。即使标准 -Wstrict-aliasing 没有发出警告,我也不确定它是否能保证生成有效的代码(但在那个给定的例子中确实如此)。

第二种情况看起来不错,因为类型转换 structure*char*被允许。然而,char* 之间是有区别的。和 char[]类型。

关于c - C 中的灵活数组和取消引用类型双关指针错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25041413/

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