您的位置:首页 > 其它

关于结构体中零长度数组的问题

2009-06-12 22:37 253 查看
在许多代码里都出现了类似的结构体
struct ast_exten {
char *exten; /* Extension name */
int matchcid; /* Match caller id ? */
char *cidmatch; /* Caller id to match for this extension */
int priority; /* Priority */
char *label; /* Label */
struct ast_context *parent; /* The context this extension belongs to */
char *app; /* Application to execute */
void *data; /* Data to use (arguments) */
void (*datad)(void *); /* Data destructor */
struct ast_exten *peer; /* Next higher priority with our extension */
const char *registrar; /* Registrar */
struct ast_exten *next; /* Extension with a greater ID */
char stuff[0];
};

就是零长度的数组

关于这个问题,存在几个需要弄清楚的地方。第一,char p[0]是否合法;其次,如果非法,按照标准,合法的代码是怎样的?

先解释第一点,在ISO/IEC 9899-1999里面,这么写铁定是非法的,这个仅仅是GNU C的扩展,gcc可以允许这一语法现象的存在。考虑以下代码:
#include <stdio.h>

int main(int argc, char* argv[])
{
char ia[0];
printf("%d/n", sizeof(ia));
return 0;
}
这个在gcc里面编译,即使你使用了-Wall参数,gcc仍然会让这段代码通过……如果需要强制编译器按照ISO C标准进行编译,你需要给出-pedantic(或者-pedantic_error)参数,这样,编译器会报告:ISO C forbids zero-size array `ia'
这个仅仅是在C99没有出台的情况下,gcc为了使用类似于C99 flexible array member而做出的一个work-around,但是现在C99出现了,并且正式支持了flexible array member的语法,这样的一个GNU C扩展就有点显得不合时宜了……按照ISO/IEC 9899-1999的要求,flexible array member的定义应当是这样:
struct foo
{
int variable;
int bar[];//here!!!!
};
这个才是符合标准要求的写法,当你的代码需要跨平台、跨编译器移植,并且需要这个特性的时候,这个才是唯一准确的写法!

本来这里有一个trick,只不过flexible array member将其标准化了而已。
原来的trick应该是写作
struct foo
{
int variable;
int i_am_a_trick[1];
};

struct foo *ptr_to_foo = malloc(sizeof(struct foo) + SOMELENGTH);
因为标准看到了这种trick可能造成的问题:
struct foo something[2];//本以可能并不是这样,对于flexible array member来说,这个会被标记为错误或者警告,防止出现问题……

extension flexible array member,是C99允许的。标准原文如下(第117页):

As a special case, the last element of a structure with more than one named member may
have an incomplete array type; this is called a flexible array member. With two
exceptions, the flexible array member is ignored. First, the size of the structure shall be
equal to the offset of the last element of an otherwise identical structure that replaces the
flexible array member with an array of unspecified length.106) Second, when a . (or ->)
operator has a left operand that is (a pointer to) a structure with a flexible array member
and the right operand names that member, it behaves as if that member were replaced
with the longest array (with the same element type) that would not make the structure
larger than the object being accessed; the offset of the array shall remain that of the
flexible array member, even if this would differ from that of the replacement array. If this
array would have no elements, it behaves as if it had one element but the behavior is
undefined if any attempt is made to access that element or to generate a pointer one past
it.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: