使用 char 数组进行 C 结构初始化

Posted

技术标签:

【中文标题】使用 char 数组进行 C 结构初始化【英文标题】:C struct initialization with char array 【发布时间】:2013-09-28 19:20:01 【问题描述】:

我有一个 C 结构定义如下:

struct Guest 
   int age;
   char name[20];
;

当我创建了一个Guest 变量并使用以下内容对其进行初始化时:

int guest_age = 30;
char guest_name[20] = "Mike";
struct Guest mike = guest_age, guest_name;

我收到关于第二个参数初始化的错误,它告诉我guest_name 不能用于初始化成员变量char name[20]

我可以这样做来初始化所有:

struct Guest mike = guest_age, "Mike";

但这不是我想要的。我想通过变量初始化所有字段。如何在 C 中做到这一点?

【问题讨论】:

您不能复制数组。使用std::string 我知道我可以使用std::string。但是如果我想坚持使用 C 风格的 char 数组呢? 您说的是 C 或 C++。现在你说 C。 我应该说清楚。我想在 C char 数组中执行此操作。编辑了我的问题。有可能吗? 【参考方案1】:

其实你可以静态初始化这个结构体:

struct Guest 
   int age;
   char name[20];
;

Guest guest =  30, 'M','i','k','e','\0';

数组的每个元素都必须明确设置,而这不能使用 c-strings 来完成。如果结构是用 char* 名称定义的,那么我们可以这样做:

struct Guest 
   int age;
   char* name;
;

Guest guest =  30, "Mike";

【讨论】:

【参考方案2】:

mike.name 是一个字符数组。您不能仅使用 = 运算符来复制数组。

相反,您需要使用strncpy 或类似的东西来复制数据。

int guest_age = 30;
char guest_name[20] = "Mike";
struct Guest mike =  guest_age ;
strncpy(mike.name, guest_name, sizeof(mike.name) - 1);

您已将此问题标记为 C++,因此我想指出,在这种情况下,您几乎应该始终使用 std::string 而不是 char[]

【讨论】:

谢谢。所以在struct的声明中使用C struct初始化来初始化char数组成员是不可能的吧? 一般来说strncpy使用时需要添加空终止符。 在这个例子中,我用括号符号初始化了struct,它将指定成员之后的所有内容归零。然而,在 strncpy 调用中有一个相关的错误,以及一些错别字,我很惊讶没有人关注。 ;) 谢谢【参考方案3】:

您可以在 C 中静态分配具有固定 char[] 数组的结构。例如,gcc 允许以下操作:

#include <stdio.h>

typedef struct 
    int num;
    char str[];
 test;

int main(void) 
    static test x=.num=sizeof("hello"),.str="hello";

    printf("sizeof=%zu num=%d str=%s\n",sizeof(x),x.num,x.str);
    return 0;

它做了正确的事情(虽然要注意 sizeof(x):它在我的机器上返回 4;而不是静态分配的总内存的长度)。

这对于从堆栈分配的结构不起作用,您可能会怀疑。

【讨论】:

(1) 我不认为 GCC 坏到不能为 sizeof("hello") 返回 6 — 但也许你指的是 sizeof(x),在这种情况下 4 是正确的回答。 (2) 这称为结构中的灵活数组成员。 (3) 初始化是一个 GCC 扩展,尽管您必须调用 -pedantic 才能让它在 static test x=.num=sizeof("hello"),.str="hello"; 处“公开:initialization of a flexible array member [-Werror=pedantic] — 编译器选项 gcc -O3 -g -std=c11 -Wall -Wextra -Werror -pedantic xx37.c”。我在 Mac OS X 10.11.6 上使用 GCC 6.1.0。 @JonathanLeffler 这个扩展是否也扩展了分配的空间以允许初始化器适应? @M.M:我不确定,但我认为是的。我没有很好地阅读 x86_64 汇编程序,但 size xx37.o 的输出(其中 xx37.c 包含此答案中的代码副本)给出了大小为 10 的数据部分,它对应于 x 的大小应该是如果它被分配为一个单元(这是必须处理 FAM 的方式)。所以,我推断 GCC 正确地完成了这项工作(考虑到它确实做到了,这并不奇怪),但我愿意证明我在这方面是错误的。 虽然这个成语确实是 gcc 扩展 [1],但我在 ISO C99 [2] 中没有看到任何禁止它的内容。 [1] gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc/Zero-Length.html [2] ISO/IEC 9899 第 6.7.8 节第 20、22 段。如果您想复习 [],第 31 段也值得一看。【参考方案4】:

mike.name 是结构内的 20 字节保留内存。 guest_name 是指向另一个内存位置的指针。通过尝试将guest_name 分配给结构的成员,您尝试了一些不可能的事情。

如果您必须将数据复制到结构中,您必须使用memcpy 和朋友。在这种情况下,您需要处理 \0 终止符。

memcpy(mike.name, guest_name, 20);
mike.name[19] = 0; // ensure termination

如果你有\0 终止的字符串,你也可以使用strcpy,但由于name 的大小是20,我建议strncpy

strncpy(mike.name, guest_name, 19);
mike.name[19] = 0; // ensure termination

【讨论】:

因此,我无法使用Guest mike = ... 形式初始化此结构的其他成员。如果我有更多字段,我必须使用mike.age = ...,; mike.id=...; memcpy(mike.name, guest_name, 20); 如果你事先不知道字符串(在编译时),是的。

以上是关于使用 char 数组进行 C 结构初始化的主要内容,如果未能解决你的问题,请参考以下文章

c ++初始化一个带有数组的结构类型

C语言中的结构体数组

具有 char 数组的 C++ 结构以不寻常的方式初始化为零

在 Swift 中使用 const char * 初始化 C-struct

C中结构数组的部分初始化

C中结构内的字符串数组,无需分配