如何使用用C零长度数组 [英] How to use zero length array in C

查看:139
本文介绍了如何使用用C零长度数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在链接中指定我们可以初始化长度为零的数组结构:

We can initialize a struct with zero length array as specified in the link:

零长度

我用以下结构:

typedef unsigned char UINT8;
typedef unsigned short UINT16;

typedef struct _CommandHeader
{
    UINT16 len;
    UINT8 payload[0];
} CommandHeader;

typedef struct _CmdXHeader
{
    UINT8 len;
    UINT8 payload[0];
} CmdXhHeader;

现在的CommandHeader.payload应指向/包含对CmdXHeader结构。即内存应该是这样的:

Now the CommandHeader.payload should point / contain to CmdXHeader struct. i.e. memory should look like:

 -------------------------------------------------------------
| CommandHeader.len | CmdXHeader.len | CmdXHeader.payload ....|
 -------------------------------------------------------------

我可以很容易的malloc CmdXHeader / CommandHeader定制化的长度。但如何分配值CmdXHeader有效载荷或如何将CmdXHeader对象链接到CommandHeader.payload?

I can easily malloc CmdXHeader / CommandHeader to customized length. But how to assign value to CmdXHeader payload or how to link a CmdXHeader object to the CommandHeader.payload?

感谢所有的答复。我解决它通过以下方式:

Thanks for all the reply. I solved it in the following way:

//Get the buffer for CmdXHeader:
size_t cmdXHeader_len = sizeof(CmdXHeader) + custom_len;
CmdXHeader* cmdXHeader = (CmdXHeader*) malloc(cmdXHeader_len);
//Get a temporary pointer and assign the data to it
UINT8* p;
p[0] = 1;
p[2] = 2;
.......

//Now copy the memory of p to cmdXHeader
memcopy(cmdHeader->payload, p, custom_len);

// allocate the buffer for CommandHeader
CommandHeader* commandHeader = (CommandHeader*) malloc (sizeof (CommandHeader) + cmdXHeader_len);

// populate the fields in commandHeader
commandHeader->len = custom_len;
memcpy(commandHeader->payload, cmdXHeader, cmdXHeader_len);

现在的commandHeader对象具有所需的内存,我们可以用我们想要的任何方式强制转换...

Now the commandHeader object have the desired memory and we can typecast with whatever way we want...

推荐答案

在结构或其他地方的末端的长度为零的数组,实际上是非法的(更precisely一个的约束违反),这是一个特定的GCC扩展。

A zero-length array at the end of a struct, or anywhere else, is actually illegal (more precisely a constraint violation) in standard C. It's a gcc-specific extension.

这几种形式的黑客结构中的一个。稍微更便携的方式做它是定义长度为1的数组,而不是0。

It's one of several forms of the "struct hack". A slightly more portable way to do it is to define an array of length 1 rather than 0.

丹尼斯里​​奇,C语言的创始人,曾称它是毫无根据的亲密关系与C实现的。

Dennis Ritchie, creator of the C language, has called it "unwarranted chumminess with the C implementation".

1999年修订的ISO C标准的推出了一款名为灵活数组成员功能​​,一个更强大的方式来做到这一点。大多数现代的C编译器支持此功能(我怀疑微软的编译器不,虽然)。

The 1999 revision of the ISO C Standard introduced a feature called the "flexible array member", a more robust way to do this. Most modern C compilers support this feature (I suspect Microsoft's compiler doesn't, though).

这是在长度问题讨论2.6 comp.lang.c常见问题解答

This is discussed at length in question 2.6 of the comp.lang.c FAQ.

至于你如何访问它,两者形成你用,你可以把它像你对待任何数组。该成员的名称衰变为指针在大多数情况下,让你索引它。只要你分配了足够的内存,你可以做这样的事情:

As for how you access it, whichever form you use, you can treat it like you'd treat any array. The name of the member decays to a pointer in most contexts, allowing you to index into it. As long as you've allocated enough memory, you can do things like:

CommandHeader *ch;
ch = malloc(computed_size);
if (ch == NULL) { /* allocation failed, bail out */ }
ch.len = 42;
ch.payload[0] = 10;
ch.payload[1] = 20;
/* ... */

显然,这只是一个大致的轮廓。

Obviously this is only a rough outline.

注意的sizeof ,当应用于类型 CommandHeader 或类型的对象,会给你一个结果是不包括柔性阵列构件

Note that sizeof, when applied to the type CommandHeader or an object of that type, will give you a result that does not include the flexible array member.

还请注意,标识符以下划线开始被保留到实现。你不应该在自己的code定义这样的标识符。有没有必要使用不同的标识符的typedef名称和结构标记:

Note also that identifiers starting with underscores are reserved to the implementation. You should never define such identifiers in your own code. There's no need to use distinct identifiers for the typedef name and the struct tag:

typedef struct CommandHeader
{
    UINT16 len;
    UINT8 payload[0];
} CommandHeader;

我还建议使用标准的类型 uint16_t uint8_t有定义< stdint.h> (假设你的编译器支持它;它也是新的C99)

I'd also suggest using the standard types uint16_t and uint8_t, defined in <stdint.h> (assuming your compiler supports it; it's also new in C99).

(实际上是开始用下划线标识符的规则稍微复杂一点。引用 N1570 ,标准的最新草案,部分7.1.3:

(Actually the rules for identifiers starting with underscores are slightly more complex. Quoting N1570, the latest draft of the standard, section 7.1.3:


      
  • 与下划线和大写字母或其他开头的所有标识符
      下划线,始终保留用于任何用途。

  •   
  • 以下划线开头的所有标识符总是保留用作标识符
      在这两个普通和标记的名称空间文件范围。

  •   

和有几个班的保留标识符。

And there are several more classes of reserved identifiers.

但不是工作了哪些标识符是安全的在文件范围内使用,哪些是安全的在其他范围内使用,它更容易只是为了避免定义以下划线开始的标识符。)

But rather than working out which identifiers are safe to use at file scope and which are safe to use in other scopes, it's much easier just to avoid defining any identifiers that start with an underscore.)

这篇关于如何使用用C零长度数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆