2017-10-28 35 views
-3
#include <stdio.h> 
#include <string.h> 

char lists[10][25]; 
char name[10]; 

void main() 
{ 
    scanf("%s" , lists[0]); 
    memcpy(name , lists[0], 25); 

    printf("%s\n" , name); 
} 

在上面的代码我预定义的字符数组“名”的大小为10。 现在,当我给输入为:有关memcpy函数如何运行的说明?

输入 - abcdefghijklmnopqrstuvwxy

我得到的输出是相同的字符串:abcdefghijklmnopqrstuvwxy

应该不会输出为:abcdefghij?

即使阵列的大小限制为10,这将如何变得可能?

+3

这是一个* undefined behavior *的例子,这意味着可能发生任何事情。包括程序正常工作。 – klutt

+1

你的代码在线以外着色,非常基本的UB。如果你想让它炸毁并重新格式化磁盘,那么你需要更多的颜色。交换这两个变量声明是值得一试的。 –

+1

大多数语言都会阻止程序员写入数组的末尾。 C没有。这是你的责任。 – jarmod

回答

1

因为它不知道它正在写入的已分配内存的大小,所以你就不知道写入额外数据的位置了。您可能不在其他平台上,或使用不同的编译器或不同的优化设置。

当将size参数传递给memcpy()时,最好考虑目标存储器的大小。

使用字符数组时,如果想要更安全地关于不超限内存,可以使用strncpy()。它会照顾在正确的地方插入尾随NULL

+0

所以,你的意思是说如果我可用的内存块是10,那么这将不会发生? – Jamzy

+1

不,如果内存是25,那么你没有问题。 C取决于程序员对内存分配和写入等方面的注意。 – Steve

+0

我的意思是说可用的物理内存只有10个,那么我将无法找到一些额外的内存,然后它会提出一个错误或什么!对 ?? – Jamzy

0

首先,数组是指针。在C中,没有像Java那样的长度检查。

当您编写char a[2];时,操作系统会为您提供2个字符的内存空间。 例如,让存储器是

|1|2|3|4|5|6|7|8|9|10|11|12| 
a 

a是指向的地址1。a[0] = 0;*(a+0) = 0相等,这意味着write 0 to the address a + offset 0

因此,如果您尝试写入未分配的地址,可能会发生意想不到的情况。

例如,让我们说我们有char a[2];char b[2];和存储器映射

|1|2|3|4|5|6|7|8|9|10|11|12| 
a b 

然后a[2] = 0等于b[0] = 0。但是如果这个地址是另一个程序的地址,那么会出现分段错误。

尝试程序(它可能没有编译器的优化工作):

#include <stdio.h> 
#include <string.h> 

char a[4]; 
char b[4]; 

void main() 
{ 
    scanf("%s" , a); // input "12345678" 
    printf("%s\n" , b); // print  "5678" 
} 

memcpy刚刚从一个地址复制到其他的数据你说的大小。

在你的例子中,你是luky,因为你访问的所有地址分配给你的程序(在你的内存页面内)。

在C/C++中,您有责任正确处理内存。另外,请记住,字符串以char \0结尾,因此在数组内我们通常有9个字符和\0

+1

我认为你在这里有一个错字:“a [0] = 0;与*(a + 1)= 0相等,意思是写0到地址a +偏移量0。 – MFisherKDX

+0

当然可以。谢谢。 (现在正确) – GramThanos

+0

“| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | ab然后a [2] = 0等于b [0] = 0 “。如果你依靠这种行为,你就会受到伤害。不知道编译器/优化器可能做什么。 – MFisherKDX