2010-12-12 82 views
3

我有一个基本的C编程问题,这里是情况。如果我正在创建一个字符数组,并且如果我想使用%s转换代码将该数组视为字符串,那么我是否必须包含空零。例如:C字符串空零?

char name[6] = {'a','b','c','d','e','f'}; 
printf("%s",name); 

此控制台输出为:

abcdef 

注意,没有一个空零数组中的最后一个元素,但我仍然打印这是一个字符串。

我是新来的编程...所以我读初学者ç书,其中规定,因为我不是在最后一个元素使用空零,我不能把它当作一个字符串。

这与上面的输出相同,尽管我包含了空零。

char name[7] = {'a','b','c','d','e','f','\0'}; 
printf("%s",name); 
+0

这是一些安全漏洞的来源。 – 2010-12-12 22:36:46

+1

+1我喜欢null零:)“那是什么样的零? “零零。” “长零。” “一个浮动零点。” “双零。” ... – pmg 2010-12-12 22:39:09

+2

一般情况下,你会这样做的方式是'char name [7] =“abcdef”(在“”中的字符串字面量自动包含NUL) – 2010-12-12 22:41:48

回答

3

你的拳头printf的输出是不可预测的具体,因为你没有包括终止零字符。如果它在您的实验中似乎有效,那只是因为随机偶然,内存中的下一个字节碰巧为零,并且作为零终止符工作。发生这种情况的可能性很大程度上取决于你声明你的name数组的位置(这不清楚你的例子)。对于一个静态数组来说,机会可能会非常高,而对于一个本地(自动)数组,你会碰到经常打印的各种垃圾。

+0

本质上,如果我想使用%s转换,我必须添加一个空零“以确保”字符串正确终止? – Michael 2010-12-12 22:55:18

+0

是的(一般情况下,只要你想用'char'数组作为C字符串就可以了);但是使用特殊的字符串初始化语法('char name [] =“abcdef”;',其中'NUL'自动添加,以及数组大小)更容易,而不是像这样指定单个字符。 – 2010-12-12 23:04:03

+0

是的......这是我读过的。非常感谢你! – Michael 2010-12-12 23:08:20

5

你只是幸运;大概在该数组结束后,在堆栈中,有一个零,所以printf在最后一个字符后停止读取。如果你的程序非常短,堆栈区域仍然是“未开发”的 - 即堆栈还没有增长到这一点 - 它很容易,它是零,因为通常现代操作系统给应用程序初始化为零页。

更正式地说:由于没有明确的终止符,你将进入未定义行为的领域,这意味着任何事情都可能发生;这样的任何事情也可能是你的程序工作正常,但这只是运气 - 而且这是最糟糕的错误类型,因为如果它一般工作正常,很难发现。

TL; DR版本:不这样做。坚持保证工作,你不会在你的应用程序中引入偷偷摸摸的bug。

2

必须在末尾的空字符。

因为运气好运,没有错误,只有运气。试试这个:

char name[6] = {'a','b','c','d','e','f'}; 
printf("%s",name); 
printf("%d",name[6]); 

你最有可能看到的是你可以读取内存,并有在它零。但这真是太幸运了。

+0

其实,如果你的程序“似乎有效”,当它做这样糟糕的事情时,你是相当** **幸运的,因为这使得它更难找到该程序。当然,只有当你写了更多(正确)的代码时,它才会在后面大打出手,现在问题似乎完全不同了。或者它会为你“工作”,当你向一个重要的人展示你的程序时会炸毁。或者...你有这个想法:) – 2010-12-13 08:14:51

+0

啊,为你工作,但不在观众面前。经典。 – slezica 2010-12-13 16:43:00

0

最有可能发生的是,那里恰巧0的存储位置名称+ 6这不是虽然定义的行为的价值,你可以在不同的系统或不同的编译器得到不同的输出。

0

是的。你做。还有其他一些方法可以做到这一点。

这种形式的初始化,自动将NUL字符放入。

char name[7] = "abcdef"; 
printf("%s",name); 

请注意,我为数组大小添加1,为该NUL留出空间。

也可以省略大小,让编译器找出它。

char name[] = "abcdef"; 
printf("%s",name); 

另一种方法是用一个指向char的指针指定它。

char *name = "abcdef"; 
printf("%s",name); 
+0

我想补充一点,你指定的最后一个方法不等于前两个:事实上,最后一个获得一个指向内存只读区域的指针,其中存储字符“abcdef”(实际上是“ name'应该是一个'const char *'),另外两个用这个值初始化一个数组,这样的数组可以被修改而没有问题。 – 2010-12-12 23:30:10

+0

是的,好点。当我是一个小孩时,你可以修改它们。 – EvilTeach 2010-12-13 00:36:31