初始化char数组的不同方法是正确的吗?

时间:2017-04-13 06:26:18

标签: c arrays initialization variable-assignment

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

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

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

  3. BUFFLEN在哪里不变。

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

      

    警告:赋值在没有强制转换的情况下从指针生成整数

    有人可以解释一下我的区别。我检查了很少的帖子,但真的很难完全理解它。

7 个答案:

答案 0 :(得分:8)

TL; DR 他们都不是初始化,第一个是 initialization ,第二个是(尝试) to) assignment

第一种情况是尝试定义char数组并使用字符串文字“Hello,I is client :)”初始化内容。语法

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

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

然而,在第二种情况下,

char

第二个陈述是错误的,如

  • char buf[BUFFLEN]; buf[BUFFLEN] = "Hello, I am client :)"; 超出了内存访问权限,它是off-by-one。这实际上会导致undefined behavior

    - FWIW,C对数组使用基于0的索引,因此对于定义大小为buf[BUFFLEN]的数组,其有效索引范围为BUFFLEN0。< / EM>

  • 考虑)语法BUFFLEN-1也无效,因为这是违反约束 ## Note 2 。检查数据类型。

    - LHS的类型为buf[BUFFLEN - <whatever>] = "some string";,您尝试分配类型为char的值(其衰减为char [])且分配无效C.您需要要复制内容,请使用strcpy()或类似内容。

##注1:

引用char*,章节§6.7.9

  

字符类型数组可以用字符串文字或UTF-8字符串初始化   文字,可选择括在括号中。字符串文字的连续字节(包括   如果有空间或数组的大小未知,则终止空字符)初始化   数组的元素。

##注2:

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

  

以下其中一项应成立: 112)

     
      
  • 左操作数具有原子,限定或非限定算术类型,右边有   算术类型;

  •   
  • 左操作数具有原子,限定或非限定版本的结构或联合   类型与权利类型兼容;

  •   
  • 左操作数具有原子,限定或非限定指针类型,并且(考虑到   两个操作数都是左值操作数在左值转换后的类型   指向兼容类型的限定或非限定版本的指针,以及指向的类型   左边的所有限定符都是右边所指示的类型;

  •   
  • 左操作数具有原子,限定或非限定指针类型,并且(考虑到   左值操作数在左值转换后将具有的类型)一个操作数是一个指针   到对象类型,另一个是指向合格或非限定版本的指针   void,左边指向的类型具有指向的类型的所有限定符   在右边;

  •   
  • 左操作数是原子,限定或非限定指针,右边是空   指针常数;或

  •   
  • 左操作数具有原型,限定或不合格的_Bool类型,右边是a   指针。

  •   

答案 1 :(得分:8)

C11

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

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

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

答案 2 :(得分:5)

您不能将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数组的多个字符。

答案 3 :(得分:2)

在您提供的示例中, 1.char buf [BUFFLEN]; (编译器默认初始化数据,即使你没有) 2. buf [BUFFLEN] =&#34;您好,我是客户:)&#34 ;; (它将它视为一个赋值操作,你不能将一个字符数组分配给另一个字符数组,就像这种语言不允许)

你可以使用strcpy char buf [BUFFLEN] strncpy(buf,&#34;你好,我是客户:)&#34;,BUFFLEN);

答案 4 :(得分:2)

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

第二种方法

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

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

答案 5 :(得分:1)

让我们说BUFFLEN = 20。

所以,根据你的代码char buff [BUFFLEN] =“你好,我是客户端:)”;

它创建一个大小为20的字符数组并分配您的字符串。如果你写的话 char buff [BUFFLEN]; buf [BUFFLEN] =“你好,我是客户:)”;

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

答案 6 :(得分:0)

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

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

c11 - 6.7.8:第14段:

  

字符类型数组可以由字符串初始化   文字或UTF-8字符串文字,可选择用大括号括起来。   字符串文字的连续字节(包括终止空值)   字符,如果有空间或数组的大小未知)   初始化数组的元素。

,第二,

char buf[BUFFLEN];

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

非法初始化字符数组。