初始化char数组的不同方法,它们是否正确?

Different ways to initialize char array, are they correct?

我在 C 中使用两种类型的 char 数组声明:

  1. char buf[BUFFLEN] = "Hello, I am client :)";

  2. char buf[BUFFLEN]; buf[BUFFLEN] = "Hello, I am client :)";

其中 BUFFLEN 是某个常数。

当我用第二种方式编译时,我收到警告但没有错误

warning: assignment makes integer from pointer without a cast

谁能给我解释一下区别。我查了几个关于它的帖子,但真的很难完全理解它。

TL;DR他们两个都不是初始化,第一个是initialization, the second one is (an attempt to) assignment.


第一种情况是试图定义一个char数组并用字符串文字"Hello, I am client :)"初始化内容。语法

 char buf[BUFFLEN] = "Hello, I am client :)";

很好,因为我们允许 ## 注 1 提供一个char 数组的字符串文字形式的初始值设定项。这个片段是有效的,所以我们在那里很好。

然而,在第二种情况下,

  char buf[BUFFLEN];
  buf[BUFFLEN] = "Hello, I am client :)";

第二个说法是错误的,因为

  • buf[BUFFLEN] 是越界内存访问,它是 off-by-one. This actually causes undefined behavior.

    -- FWIW,C 对数组使用基于 0 的索引,因此对于大小为 BUFFLEN 的数组,其有效索引范围为 0BUFFLEN-1.

  • (considering) 语法 buf[BUFFLEN - <whatever>] = "some string"; 也是无效的,因为这是违反约束的 ## 注 2。检查数据类型。

    -- LHS 的类型为 char,您正在尝试分配类型为 char [] 的值(衰减为 char*)并且分配无效 C.您需要复制内容,使用strcpy()或类似的。


##注1:

引用 C11,章节 §6.7.9

An array of character type may be initialized by a character string literal or UTF−8 string literal, optionally enclosed in braces. Successive bytes of the string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

##注2:

C11,章节 §6.5.16.1,简单赋值约束

One of the following shall hold:112)

  • the left operand has atomic, qualified, or unqualified arithmetic type, and the right has arithmetic type;

  • the left operand has an atomic, qualified, or unqualified version of a structure or union type compatible with the type of the right;

  • the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;

  • the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) one operand is a pointer to an object type, and the other is a pointer to a qualified or unqualified version of void, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;

  • the left operand is an atomic, qualified, or unqualified pointer, and the right is a null pointer constant; or

  • the left operand has type atomic, qualified, or unqualified _Bool, and the right is a pointer.

char buf[BUFFLEN] = "Hello, I am client :)";

这将创建一个字符数组并使用字符串文字的内容对其进行初始化。

char buf[BUFFLEN];

buf[BUFFLEN] = "Hello, I am client :)";

这会创建一个未初始化的字符数组,然后执行越界访问。此代码段的行为未定义。

不能将c字符串赋值给数组,只能在声明时初始化,所以

char buf[BUFFLEN] = "Hello, I am client :)";

没关系。

但是如果你想在运行时设置它,你必须使用函数作为 strcpy:

strcpy(buf, "Hello, I am client :)");

显然,您至少必须确保

BUFFERLEN >= strlen("Hello, I am client :)") + 1

编辑

要获得安全的解决方案,您应该

char buf[BUFFLEN] = {0};

snprintf(buf, sizeof(buf), "%*s", (int)(sizeof(buf)-1), "Hello, I am client :)");

snprintf 您授予:

  • 那个输出字符串我总是空终止
  • 由于 sizeof(buf)
  • ,buf 的大小受到尊重
  • 此外,使用 "%*s" 格式说明符和 (int)(sizeof(buf)-1) 你强制复制一些适合你的 buf 数组的字符。
char buf[BUFFLEN] = "Hello, I am client :)";

有效的字符数组初始化,但不指定用字符串文字初始化的字符串的边界,因为编译器会自动为整个字符串文字分配足够的space,包括终止空字符。

c11 - 6.7.8:第 14 段:

An array of character type may be initialized by a character string literal or UTF−8 string literal, optionally enclosed in braces. Successive bytes of the string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

第二,

char buf[BUFFLEN];

buf[BUFFLEN] = "Hello, I am client :)";

字符数组初始化非法。

在您提供的示例中, 1.charbuf[缓冲区]; (编译器默认初始化数据,即使你没有) 2. 缓冲区 [缓冲区] = "Hello, I am client :)"; (它把它当作一个赋值操作,你不能将一个字符数组赋值给另一个字符数组,就像这种语言不允许的那样)

你可以使用strcpy 字符缓冲区 [BUFFLEN] strncpy(buf, "Hello, I am client :)", BUFFLEN);

假设 BUFFLEN = 20。

所以,根据你的代码 char buff[BUFFLEN]="Hello, I am client :)";

它创建一个大小为 20 的字符数组并分配您的字符串。那么如果你写 字符缓冲区 [BUFFLEN]; buf[缓冲器] = "Hello, I am client :)";

您实际上是在尝试访问或初始化 buf[20],这会导致数组越界。因为可以从 0 索引到 19 访问 buf。

= "Hello, I am client :)"; 是一种特殊的初始化字符数组的方法,它只在数组的定义处有效,即在类型为 (char ...[]).
的行中 在内存设置期间,它在 main 开始之前创建数组并用字符串中的字符填充它。

第二种方法

  • 定义了一个char数组,没有初始化它char buf[BUFFLEN];
  • 只在数组后面进行一次写访问(其他答案评论了什么)buf[BUFFLEN] =
  • 试图在那个非法位置写入 "char"...
  • ... 指向字符串常量的指针 "Hello, I am client :)";

定义时初始化后,需要使用函数将字符串复制到 char 数组,例如strncpy()