我编写了一个简单的程序来以这种方式计算字符串的长度。 我知道还有其他方法。但我只是想知道为什么这个程序正在提供这个输出。
#include <stdio.h>
int main()
{
char str[1];
printf( "%d", printf("%s", gets(str)));
return 0;
}
输出:
(null)6
答案 0 :(得分:3)
除非你总是从标准输入传递空字符串,否则你正在调用未定义的行为,因此输出几乎可以是任何东西,并且它也可能崩溃。 str
不能是格式正确的C字符串,超过零个字符。
char str[1]
为一个单个字符分配存储空间,但该字符必须是NUL
字符才能满足C字符串约束。您需要创建一个足够大的字符数组来保存您使用gets
编写的字符串。
&#34;(空)6&#34;因为输出可能意味着gets
返回NULL
,因为它由于某种原因失败或者堆栈被损坏,使得返回值被零覆盖(根据未定义的行为解释)。 6以下&#34;(null)&#34;是预期的,因为printf
的返回值是打印的字符数,&#34;(null)&#34;是六个字符长。
答案 1 :(得分:1)
它调用未定义的行为。在这种情况下,你可能得到任何东西。如果您没有传递空字符串,则至少str
应为2
个字节。
答案 2 :(得分:1)
您的计划存在一些问题。
首先,你将char缓冲区定义得太短,一个字符串的1个字符串缓冲区只能容纳一个字符串,空字符串。这是因为您需要在字符串末尾使用null来终止它。
接下来,您正在使用非常不安全的gets
函数(因为您的编译器几乎肯定会警告您),因为它只是盲目地接受输入并将其复制到缓冲区中。由于您的缓冲区长度为0 +终止符,您将自动将字符串的末尾覆盖到其他内存区域,这些区域可能并且可能包含重要信息,例如rsp
(您的返回指针) 。这是粉碎堆栈的经典方法。
第三,您将printf
函数的输出传递给另一个printf
。 printf
不是为格式化字符串和返回字符串而设计的,还有其他功能。通常,您要使用的是sprintf
并将其传递给字符串。
请阅读有关此类事情的文档,如果您在尝试编程之前不确定是否有任何特定内容,请阅读。您似乎对许多重要C函数的基本用法感到困惑。
答案 3 :(得分:0)
声明变量时,会保留一些空间来存储值。
保留空间可以是以前由其他人使用的空间
代码并具有价值。当变量超出范围或free
d时
该值不被删除(或者可能是,任何事情都可以。)只有程序才能访问
该变量被撤销。
当你从一个单一的位置读取时,你可以得到任何东西。
这是未定义的行为,你正在这样做,
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
上的输出为0
答案 4 :(得分:0)
对于上面的程序,你的输入是“(null)”,所以你得到“(null)6”。这里“6”是printf
的输出(成功打印的字符数)。