#include <stdio.h>

int main() {
    char a = 5;
    char b[2] = "hi"; // No explicit room for `\0`.
    char c = 6;

    return 0;
}

每当我们写一个用双引号括起来的字符串时,C会自动为我们创建一个字符数组,其中包含该字符串,以\0字符结尾

在上面的示例中,b只能容纳2个字符,因此空终止字符没有位置可放置,而编译器正在重新组织内存存储指令,以便ac在内存中存储在b之前,为数组末尾的\0腾出空间.

这是意料之中的还是我的行为没有定义?

推荐答案

如果数组的大小至少足以容纳字符串besides中的所有字符(即空终止符),则允许使用字符串初始化chararray.

这一点在C standard页的第6.7.9p14节中有详细说明:

字符类型的数组可以由字符串初始化 文本或utf−8字符串文本,可以 Select 用大括号括起来. 字符串文字的连续字节(包括终止NULL 字符,如果有空间或数组大小未知) 初始化数组的元素.

但是,这也意味着不能将数组视为字符串,因为它不是以null结尾的.如前所述,由于notb上执行任何字符串操作,所以代码很好.

你要做的是用一个太长的字符串初始化,即:

char b[2] = "hello";

因为这给出的初始值设定项比数组中可以容纳的初始值设定项多,并且违反了约束.第6.7.9p2节规定如下:

初始化者不得试图为实体中不包含的对象提供值

如果要像这样声明和初始化数组:

char b[] = "hi"; 

那么b将是一个大小为3的数组,其大小足以容纳字符串常量中的两个字符加上终止空字节,从而使b成为字符串.

总结一下:

如果数组具有固定大小:

  • 如果用于初始化它的字符串常量比数组短,数组将包含字符串中的字符,连续元素设置为0,因此数组将包含字符串.
  • 如果数组足够大,可以包含字符串的元素,但不包含空终止符,那么数组将包含字符串中没有空终止符的字符,这意味着数组不是字符串.
  • 如果字符串常量(不包括空终止符)比数组长,这是一个约束冲突,会触发undefined behavior

如果数组没有显式大小,则数组的大小将调整为保持字符串常量加上终止空字节.

C++相关问答推荐

从C函数调用asm函数时生成错误的BLX指令(STM32H753上的gcc)

在#include中使用C宏变量

为什么在函数内部分配内存空间时需要添加符号?

为什么内核使用扩展到前后相同的宏定义?

测量ARM MCU中断延迟的问题

平均程序编译,但结果不好

CC2538裸机项目编译但不起作用

从uint8_t*转换为char*可接受

将多项式从文件.txt加载到终端时出现问题

C语言中浮点数的取整方式浮点数尾数超过23位时如何取整剩余部分

为什么电路板被循环删除?

Fprintf正在写入多个 struct 成员,并且数据过剩

我可以创建适用于不同endian的 colored颜色 struct 吗?

无算术运算符和循环的二进制乘法

在git补丁中自动添加C的宏

c如何传递对 struct 数组的引用,而不是设置 struct 的副本

当另一个指向 const 的指针观察到数据时,通过指针更改数据是否安全?

使用复合文字数组初始化的指针数组

如何正确探测平台设备?

为什么简单的 ELF 二进制文件中存在重叠和未对齐的段?