/ *我观察到的是:
如果我给“abcd” 然后输出是:“abc”“d”“dude”
等等* /
#include<stdio.h>
main()
{
char a[5]="help",b[3],c[10]="dude";
scanf("%s",b);
printf("\t%s",b);
printf("\t%s",a);
printf("\t%s",c);
}
/* what i dont get is :
Here iam gaving a string to b(array), why, if the string has more than the
required no. of charecters, its printing those charecters in other arrays
(though i had not assiged scanf to other arrays )?
答案 0 :(得分:5)
请记住,C中的字符串需要空终止符。如果没有空间,打印将继续“到下一个nul”。以下是您的内存在初始化中的表现:
h e l p \0 \0 \0 \0 d u d e \0
^ ^ ^
a b c
当您在ab
指向的位置读取字符串b
时:
h e l p \0 a b \0 d u d e \0
^ ^ ^
a b c
一切都很好。但是abc
给出了:
h e l p \0 a b c \0 u d e \0
^ ^ ^
a b c
当您打印b
时,您将获得abc
;打印c
不会给你任何东西(第一个字符是'\0'
)。
最后,输入abcd
即可获得
h e l p \0 a b c d \0 d e \0
^ ^ ^
a b c
打印c
将导致"d"
- 正如您所见。
事实上,事物存储在内存中的顺序不是“定义的”,尽管编译器通常会执行与上面类似的操作。因此,虽然您知道不能写入不属于您的内存,但您无法确定在执行此操作时会发生什么(如您的情况)。这就是为什么它被称为“未定义的行为”。你不能依赖其他编译器给你相同的结果 - 甚至相同的编译器给你相同的结果......
有意义吗?
当然,解决方案是为b
分配更多空间。这会导致'\0'
和b
之间的c
更多,并且不会被覆盖。
编辑 - 我刚刚意识到b
和a
的存储顺序似乎与我刚才描述的顺序相反 - 因为它是{{ 1}},而不是被覆盖的a
。这表明编译器订购的东西非常愉快,并且当我写详细的答案时我应该戴上眼镜。但原则完全一样 - 所以我会“把剩下的作为学生的练习”。
答案 1 :(得分:1)
您的数组按以下顺序放入内存
c [10],b [3],a [5]
因此,如果数组b将包含的字符超出其容纳范围,那么它的某些字符将重叠数组a, 考虑这两个数组,b和a,因为它们在内存中
b [0] b [1] b [2] a [0] a [1] a [2] a [3] a [4]
当你在b中获得“abc”时,你得到了
b[0] b[1] b[2] a[0] a[1] a[2] a[3] a[4]
'a' 'b' 'c' '\0' 'e' 'l' 'p' '\0'
执行语句后
printf("\t%s",b);
printf("\t%s",a);
输出
"abc" ""
因为[0]包含'\ 0'
当你输入“abcd”时,你得到了
b[0] b[1] b[2] a[0] a[1] a[2] a[3] a[4]
'a' 'b' 'c' 'd' '\0' 'l' 'p' '\0'
,输出
"abcd" "d"
因为[0]包含'd'而[1]包含'\ 0'
答案 2 :(得分:0)
b[3]
是一个包含3个字符的数组。但是,字符串abc
由4个字符组成,最后一个字符为\0
,表示字符串的结尾。因此,如果您希望能够存储abc
,则需要至少声明一个包含4个字符的数组,而不是3个
答案 3 :(得分:0)
当您输入abc
作为输入时,您的数组b
会被填满(因为它只有3个位置)并且没有留给\0
字符的空间。因此,当您尝试将其作为字符串打印时...它会溢出并导致错误
要使字符串可打印,必须采用以下格式:
stringtext\0
但是当您用完数组b
中的所有空格时,在打印时没有为\0
留出空间,则会出现错误
此代码中的错误也是错误的:
scanf("%s",&b);
它应该是:
scanf("%s",b);
答案 4 :(得分:0)
当你将“abc”放入b[3]
时,它会越过数组的末尾。 abc
字符串是四个字节,因为它在末尾有一个nul终止符。
由于它是未定义的行为,任何技术上都可能发生,但实际发生的是字符串末尾的nul覆盖内存中下一个变量的第一个字符,使其成为空字符串。
最快的解决方案是确保您的字符数组足以存储所有字符和终结符:
char b[4] = "abc";
或者让编译器为这个特殊的简单情况处理它:
char b[] = "abc";
答案 5 :(得分:0)
所以真正发生的事情是你要超出数组的末尾并覆盖内存。
当您提供“ab”作为b
的输入时,它的作用是因为b
足以存储'ab'和\0
,正如其他人所提到的那样。
当您提供'abc'作为输入时,b
没有足够的空间分配来存储abc和null
所以它只存储'abc'然后null似乎写入了a
数组的第一个字节,这意味着它只是一个空字符串......或者它可能不是,这是未定义的部分。谁知道你的阵列外面存储了什么。事实上你可能会很幸运,因为你定义的数组最有可能是连续的内存。
当您提供“abcd”作为输入时,d
和null
会被写入a
数组。
很多时候,在不太简单的程序中,你会得到一个像这样的编程错误的SEGV。
答案 6 :(得分:0)
这只是未定义行为的情况之一。 b[3]
可以存储三个字符的字符串(包括\0
),但是当您的输入为abc
时,它是四个字符的字符串,您无法将其存储在数组{{1}中}。你会得到任何东西。