2013-10-19 35 views
1

/*我观察到的是:为什么这个数组是分配给非指定的数组?

  1. 当我给串像 “AB” 以B(阵列)
    则输出是: “AB”, “帮助”, “哥们”
  2. 当我给“ABC”
    然后输出为: “ABC” “” “哥们”
  3. 如果我给 “ABCD” 然后输出为: “ABC”, “d”, “哥们”

    等*/

    #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)? 
    
+1

这是未定义的行为。 – chris

+0

什么!我没有得到它? – Srinadh

+0

'scanf(“%s”,&b);'你不需要'&',''b'已经是一个指针了 –

回答

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'

+0

了解,谢谢老兄:) – Srinadh

0

b[3]是一个由3个字符组成的数组。然而字符串abc由4个字符组成,最后一个字符是\0,表示字符串结束。所以,如果你想是能够存储abc,你需要的时候你给abc输入您的阵列b被填充到至少声明的4个字符数组,而不是3

+0

好的,我编辑了那个&b;但是我想知道的是一个地址,b,c是不同的,当我调用printf与数组的关系时,它应该打印什么数据存储在那里,而不是它的打印数据,我给b,离开调用另一个数组说,那是我的问题为什么它发生那样的 – Srinadh

0

(因为它只有3个名额)并没有空间留下\0字符。因此,当您尝试将其打印出来作为字符串..它溢出并导致错误

对于可打印的字符串,它必须是以下格式: stringtext\0但是当您用完所有阵列中的空间b你没有留下任何空间\0,当您打印出来的结果,存在误差

而且这种说法是错误的代码:

scanf("%s",&b); 

它应该是:

scanf("%s",b); 
+0

好的,我编辑过&b;但我想知道的是a,b,c的地址是不同的,当我调用printf与数组的关系时,它应该打印出什么数据存储在那里,而不是它的打印数据,我给b,离开打电话给其他阵列说一个,这就是我的问题为什么它发生的那样 – Srinadh

+0

@Srinadh ..我不明白你的问题 – sukhvir

0

将“abc”放入b[3]时,它将超出数组的末尾。 abc字符串是四个字节,因为它在末尾有一个nul终止符。

由于它是未定义的行为,任何事情都可以在技术上发生,但实际发生的事情是,字符串末尾的nul将覆盖内存中下一个变量的第一个字符,使其成为空字符串。

迅速的解决办法是,以确保您的字符数组足够大来存储所有字符加上终结者:

char b[4] = "abc"; 

或者让编译器处理它为这个特殊的简单情况:

char b[] = "abc"; 
+0

好的,我编辑过&b;但我想知道的是a,b,c的地址是不同的,当我调用printf与数组的关系时,它应该打印出什么数据存储在那里,而不是它的打印数据,我给b,离开打电话给其他阵列说一个,这就是我的问题,为什么它发生这样的 – Srinadh

+0

@Srinadh,我没有提到运营商的地址。你所需要做的就是确保你的数组足够大。 – paxdiablo

5

请记住,C中的字符串需要空终止符。如果没有空间,打印将继续“到下一个节点”。这里是你的记忆力如何看待初始化:

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'bc之间,并且没有被覆盖。

编辑 - 我只是意识到,这似乎在其中存储ba顺序是倒着从我刚才怎么描述它 - 因为它是a,不c被覆盖掉了。这表明编译器可以随心所欲地命令,并且在我写出详细的答案时我应该戴上眼镜。但是原理完全一样 - 所以我会“把剩下的作为学生的练习”。

+0

+1人非常精细。 –

+0

所以你说的是一些编译器并排排列数组,如果我给出额外的数据,那么它会覆盖它的相邻日期,对吧? – Srinadh

+0

@Srinadh - 是的,这正是我所说的。 – Floris

0

所以真正发生的是你正在超出数组的末尾并覆盖内存。

当您提供'ab'作为b的输入时,它的工作原理是因为b足够大以存储'ab'和\0,正如其他人所提及的。

当您提供“ABC”输入,b没有足够的空间分配给商店ABC和null所以只商店“ABC”,然后将空似乎得到写入a阵列的第一个字节,这意味着它只是一个空字符串......或者它不是,这是未定义的部分。谁知道存储在阵列外部的是什么。只是碰巧你可能会很幸运,因为你定义的数组很可能在连续的内存中。

当您提供'abcd'作为输入时,dnull被写入a阵列。

很多时候在不太简单的程序中,你会得到一个像这样的编程错误的SEGV。

0

这只是未定义行为的情况之一。 b[3]可以存储三个字符的字符串(包括\0),但是当您的输入为abc时,它是四个字符的字符串,并且不能将其存储在数组b中。你会得到任何东西。

相关问题