我在c中初始化一个字符串(字符数组),我注意到即使在字符串中输入第二个null字符( 0),它也被忽略并且不会返回任何错误。请参阅下面我的意思:
#include <stdio.h>
int main()
{
char word[]= {'H','e','l','l','o',' ',' '};
char word2[]= "Hello ";
printf("Word is : %sn",word); // Prints "Hello"
printf("Word 2 is : %sn",word2); // Prints "Hello" as well
return 0;
}
您能解释一下为什么吗?
在C中,一个"字符串"作为定义为NUL终止的非NUL字符的序列。因此,第二个nul不是字符串的一部分。第一个标记结束 - 这就是printf
知道使用%s
格式指定器时要打印多少个字符的方式。
不确定您的期望。
以' '
结尾的任何字符数组都是字符串。字符串结束后发生的事情并不重要,因为字符串已经结束。
这也很好:
const char *two = "hello there";
printf("%sn", two);
此打印
hello
嵌入式' '
之后的字符无关紧要,它们不是从two
开始的字符串的一部分,所以printf()
当然不在乎。
当然,您也可以将其余字符视为字符串:
printf("%sn", two + 6);
这将打印
there
由于下半年也是一个有效的字符串(像这样的双重引用的文字添加了终结者)。因此,以某种方式,two
包含两个字符串,这是我的意思。
nul字符(或null字符(如果您正在读取C标准))终止C字符串。这是一个指示器,因此您无需将字符串的大小拖动。而且,没有什么可以阻止其他值放在缓冲区中的其他值,包括其他NUL字符。实际上,C标准库甚至具有破坏性的strtok
功能,该功能将此字符串内部放置为"令牌化"的一部分。
c(例如 printf
)中的大多数字符串操作知道何时会在找到一个null终结器后停止读取字符串。它停止搜索。
实际上,printf
并非旨在打印零终端。C中的所有字符串都旨在以一个结尾,因此,如果它们是打印的,则每个字符串在输出中也将具有" 0"。那将是非常毫无意义的。
第二个null字符在字符串中忽略
不,它不忽略。如果您运行此示范程序
#include <stdio.h>
int main(void)
{
char word[]= {'H','e','l','l','o',' ',' '};
char word2[]= "Hello ";
printf( "sizeof( word ) = %zun", sizeof( word ) );
printf( "sizeof( word2 ) = %zun", sizeof( word2 ) );
}
您将获得以下结果
sizeof( word ) = 7
sizeof( word2 ) = 8
这是所有零字符都包含在字符阵列中。
考虑到字符串文字还包含不可见的null终止字符。那就是这个字符串字面的"Hello "
(具有char[8]
类型)存储在{ 'H', 'e', 'l', 'l', 'o', ' ', ' ', ' ' }
。
冗余零字符被某些函数忽略,例如函数 strlen
或函数 printf
当格式指定器 %s
使用时,因为这些函数将字符数组视为包含字符串,这是由零字符界定字符的序列。<<<<<<<<<<<<<<<<。/p>
此外,您可以初始化为零字符数组的所有元素。例如
char s[5] = { ' ' };
此声明等于
char s[5] = { ' ', ' ', ' ', ' ', ' ' };
,您甚至可以写
char s[] = " ";
实际上,此声明等于数组s
的先前声明,即数组将包含5
零字符。
如果您执行此语句
printf( "%zun", sizeof( s ) );
您将获得预期的5
。但是,如果您执行此语句
printf( "%zun", strlen( s ) );
或此语句
printf( "%sn", s );
您将获得0或(在第二种情况下)将没有显示任何内容,除非光标将在下一行中移动。
您实际上在第二个数组中有3 ' '
s。但是请注意, ' '
或ascii nul 被认为是C中字符串的定界符,实际上,正如其他人在C中所说的那样,字符串不过是一组字节,然后是' '
字节。p>因此,您的假设应该使用" extra " ' '
s做一些特殊的事情是错误的。实际上,我说" extra ",因为即使它们是数组的一部分,它们也不是字符串的一部分,并且确保您可以尝试
char string[] = "Example Example";
您会看到,如果您使用printf()
,则不会打印' '
之后的整个" 示例",也不会通过strlen()
或任何str
* funcion考虑。此外,它原则上具有2个' '
,一个明确插入的,另一个是在第二个" 示例"之后隐式添加的。 "。