【发布时间】:2014-07-30 15:54:10
【问题描述】:
当我尝试使用 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; // ???
【问题讨论】:
-
发出警告,因为它违反了规则。您是否对为什么前两个案例没有触发警告感兴趣,或者正在寻找解决方法?
-
我很感兴趣为什么第一个案例没有触发警告。我知道两种解决方法:联合和“组合继承”。 (对不起,我的英语不好:)
标签: c strict-aliasing flexible-array-member