如果我不给它一点额外的空间,就会发疯。 任何人都可以解释这里发生了什么?

首先,我想说我是C / C ++的新手,我最初是一名PHP开发人员,所以我习惯于以任何我喜欢的方式滥用variables。

C是一个严格的国家,编译器不是很喜欢我这里,我习惯于违反规则去完成任务。

无论如何,这是我的一段简单的代码:

char IP[15] = "192.168.2.1"; char separator[2] = "||"; puts( separator ); 

输出:

 ||192.168.2.1 

但是,如果我将separator的定义更改为:

 char separator[3] = "||"; 

我得到所需的输出:

 || 

那么为什么我需要给这个男人额外的空间,所以他不和他之前的男人睡觉?

这是因为当separator长度被强制为2时,会得到一个不以null结尾的string。

一定要记住为空终止符分配一个额外的字符。 对于长度为N的string,您需要N+1字符。

一旦违反了这个要求,任何期望以空值终止的string(包括puts()函数)的代码将会运行到未定义的行为。

你最好的select是不强制任何特定的长度:

 char separator[] = "||"; 

将分配一个正确大小的数组。

C中的string是NUL终止的。 这意味着一个由两个字符组成的string需要三个字节(两个字符,第三个字符表示string的结尾)。

在你的例子中,可以省略数组的大小,编译器将分配正确的存储量:

 char IP[] = "192.168.2.1"; char separator[] = "||"; 

最后,如果你用C ++而不是C编码,最好使用std::string

如果你正在使用C ++,我build议使用std :: string类而不是Cstring – 更容易和更容易出错的恕我直言,尤其是对于有脚本语言背景的人。

每个string的末尾都有一个隐藏的nul字符“\ 0”。 你必须留下空间。

如果你这样做

 char seperator[] = "||"; 

你会得到一个3号string,而不是2号string。

因为在Cstring中nul终止(它们的末尾标有0字节)。 如果你声明分隔符是一个两个字符的数组,并给它们两个非零值,那么就没有终结符! 因此,当你puts数组的时候,几乎所有东西都可以加到最后(不pipe在arrays末尾的内存中发生了什么 – 在这种情况下,看起来就是IP数组)。

编辑:这下面是不正确的。 见下面的评论。

当数组长度为3时,额外的字节恰好有0,这就终止了string。 然而,你可能不能依赖这种行为 – 如果这个值是未初始化的,它可以包含任何东西。

在Cstring结尾有一个特殊的'\0'字符,所以你的分隔符"||" 实际上是一个字符更长。 puts函数只是打印每个字符,直到它遇到'\0' – 在你的情况下一个IPstring后面。

在C中,string在末尾包含一个(不可见的)空字节。 你需要考虑那个空字节。

 char ip[15] = "1.2.3.4"; 

在上面的代码中, ip有15个字符的空间。 14个“常规字符”和空字节。 这太短了:应该是char ip[16] = "1.2.3.4";

 ip[0] == '1'; ip[1] == '.'; /* ... */ ip[6] == '4'; ip[7] == '\0'; 

由于目前还没有人指出:如果你这样声明你的variables,那么这些string将被自动地以null结尾,而且你不必乱用数组的大小:

 const char* IP = "192.168.2.1"; const char* seperator = "||"; 

但请注意,我假设你不打算改变这些string。

但是如前所述,C ++中的安全方式是使用std :: string类。

AC“string”总是以NULL结尾,但是如果写入char separator [2] =“||”,则不会将其赋给string。 在第一种情况下,它会写这个\ 0,直到它find一个\ 0,这里你可以看到它在IP地址的末尾find的地方。 有趣的是,你甚至可以看到局部variables是如何放在堆栈上的。

行: char seperator[2] = "||" ; 应该得到你未定义的行为,因为该字符数组的长度(包括最后的null)将是3。

另外,你用什么编译器编译了上面的代码? 我用g ++编译,并把上面的行标记为错误。

C \ C ++中的string是空终止的,即末尾有一个隐藏的零。

所以你的分隔符string将是:

 {'|', '|', '\0'} = "||"