-1

任何人都知道为什么 printf 在输出时连接这两个变量,但前提是没有指定字符串的长度?

#include <stdio.h>
int main(){
char myname[3] = "tim";
char myage[3] = "ten";
printf("myname is:%s \n", myname);
printf("myage is:%s \n", myage);
}

我的名字是:蒂姆

我的年龄是:tentim

...但是当我没有指定字符串的长度时,它似乎可以按我的预期工作,而无需打印两个变量。

#include <stdio.h>
int main(){
char myname[] = "tim";
char myage[] = "ten";
printf("myname is:%s \n", myname);
printf("myage is:%s \n", myage);
}

我的名字是:蒂姆

我的年龄是:十

4

4 回答 4

6

您将数组声明为具有大小3,但您尝试在4其中存储元素。由于只有3元素有足够的内存,所以最后一个元素(字符串 null 终止符\0)没有剩余内存,这会使您的字符数组没有 null 终止符。
请注意,c 中的字符数组应为空终止,以便您可以使用printf. 这是因为printf简单地遍历字符数组直到遇到\0. 在您的第一个示例中,由于数组从未\0终止,因此您最终得到的是未定义的行为。(实际上,pintf将继续打印直到遇到\0并且在读取超出分配给数组的内存范围的过程中

在第二种情况下,由于您没有自己指定大小,因此根据字符串中指定的元素数量选择适当的大小,即:4 并且\0终止就位。

于 2013-04-21T15:10:04.123 回答
4

您没有在数组中为空终止符留出足够的空间。在 C 中,当您使用长度完全相同的字符串初始化 char 数组时,会删除空终止符。

char myname[3] = "tim"; // equivalent to char myname[3] = {'t','i','m'};
char myage[3] = "ten"; // equivalent to char myage[3] = {'t','e','n'};

如果没有空终止符,printf 函数不知道何时停止打印字符串,因此它会一直转到myage数组之后的下一个内存位置,这恰好是myname数组的存储空间。堆栈可能如下所示:

t <- beginning of myage
e
n
t <- beginning of myname
i
m
\0  <- a null terminator, by coincindence.

名字后面没有其他垃圾的事实只是一个巧合。任何东西都可能存储在您的myname数组之后,但在您的情况下它是一个空字符,因此 printf 停止打印。

如果您没有为数组指定大小,则选择比字符串长度大一的大小,以便可以存储空终止符:

char myname[] = "tim"; // equivalent to myname[4] = {'t','i','m','\0'};
char myage[] = "ten";  // equivalent to myage[4] =  {'t','e','n','\0'};

现在您的空终止符已明确放置,您的堆栈如下所示:

t <- beginning of myage
e
n
\0 <- explicit null terminator
t <- beginning of myname
i
m
\0  <- explicit null terminator.

现在 printf 函数确切地知道何时停止打印。

于 2013-04-21T15:25:05.957 回答
1

%s指令对应于指向字符串的参数。字符串是一个以第一个结尾的字符序列'\0'。但是,您没有为第一个示例中的数组提供足够的空间 a '\0',因此这些数组不包含字符串。

printf 认为存在一个字符串,并继续打印字符,直到遇到'\0'属于字符串末尾的那个字符。如前所述,没有'\0'字符是因为没有空间。您的代码导致 printf 访问数组边界之外的字节,这是未定义的行为。

于 2013-04-21T15:38:27.157 回答
0

并且假设myname[3]myage[3]一个终止的地方\0。因此,您实际上只能在每个数组中存储2 个符号。

在第二种情况下,编译器自动设置大小等于4足以存储字符串的大小。

于 2013-04-21T15:14:08.643 回答