2012-08-08 26 views
2

您好我有一个简单的代码,其打印系统字符阵列的三个字符如下所示打印字符数组的前几个字符?

void main() 
{ 
    char str[]={65,66,67}; 
    printf("%.3s",str); 
} 

这给输出ABC,但我想知道,因为这不是一个字符串意味着它不是NULL终止,则如何可以%s工作,并给出正确的结果?

+1

你写了'%.3s',而不是'%s'。 – ecatmur 2012-08-08 16:13:35

+0

我真的试图问是否因为它打印的前三个字符是%3。 – haris 2012-08-08 16:14:47

+0

@ecatmur:我故意做到了 – haris 2012-08-08 16:15:49

回答

10

由于您传递了字符串的长度,因此printf不需要0结束符。

7.21.6.1 - 8

如果精度为SPECI音响ED,不超过很多字节更多是 写入。如果精度未指定或大于数组的大小 ,则数组应包含空字符。

+0

对不起,没有得到你?什么意思是“它恰好在内存中找到0字节”? – haris 2012-08-08 16:13:20

+0

@haris不,我错了,我没看到'.3'部分,对不起。 – cnicutar 2012-08-08 16:13:36

+1

对于OP,请记住字节数并不总是等于字符数。 Unicode字符最多可能需要2个字节! – jn1kk 2012-08-08 16:17:51

2

它的工作原理是因为您提供了精度修饰符。 %.3s字面意思是从输入中打印前3个字节。如果你要删除修饰符(“%.3s” - >“%s”),这段代码仍然会无错地生成,但运行时结果是不可预测的(欢迎攻击者利用)。

0

为了阐明上面的回答(通过@cnicutar和dans3itz):将以下代码打印 “ABCDE”,即printf扫描阵列到第一空字符(0字节):

#include <stdio.h> 

int main() { 
    char str[]={65,66,67}; 
    char c = 68; 
    int x = 69; 
    int y = 70; 
    int z = 0; 
    int w = 71; 
    printf("%s", str); 
    return 0; 
} 

Fint w = 71;)不打印。

+0

这是完全错误的,你告诉我如何在str只有三个字节的时候打印ABCDE ... – haris 2012-08-08 16:34:45

+0

@haris,在做出明智的结论之前,你可能想要编译和运行。这里是我的Mac上的结果(i686-apple-darwin9-gcc-4.0.1):'user @ host:〜$ gcc -o test test.c user @ host:〜$ ./test ABCDE' – khachik 2012-08-08 16:42:34

+0

@ haris,'str,c,x,y,z,w'存储在堆栈中,所以'str'指向包含'65,66,67,68,69,70,0,71'的存储块。这就是为什么'printf'需要'ABCDE'。 – khachik 2012-08-08 16:45:19

0

@khachik我不认为这个片段按照您的预期运行。我无法使用GCC 4.2在OS X上重现结果; 4.7或Clang 3.1

+0

这必须是评论,而不是答案。该片段按发布的方式运行。我编译,运行并发布了代码,没有任何期望。 – khachik 2012-08-08 16:57:37

+1

我缺乏代表。现在发表评论。但是,您的答案的上下文意味着执行结果的期望。原谅我,如果我误解了这一点。这篇文章的目的是强调该代码的不可预测性。铿锵3.1和GCC产生不同的结果。此外,每次执行应用程序时,GCC版本都会产生不同的结果。 – dans3itz 2012-08-08 17:08:04

+0

我的答案是解释可能发生的情况,如果“%s”用于最后没有空字符的数组。该行为不能按预期考虑,因此不得使用。将没有空终止符的数组传递给“%s”而没有精确指定符是错误的。我不知道我还能解释这件事。 – khachik 2012-08-09 07:09:35