2013-11-28 182 views
0

我遇到了memcpy()的问题,而且我对我出错的地方没有线索。memcpy()似乎没有工作

代码可以在这里看到:http://pastebin.com/tebksExR

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

typedef struct tmp__ { 
    unsigned int num; 
    unsigned short id; 
    unsigned short type; 
} tmp_str; 

int 
main(int argc, char **argv) 
{ 
    tmp_str hdr; 
    char *str = NULL; 

    str = calloc(18, sizeof(char)); 
    memset(&hdr, 0, sizeof(hdr)); 

    hdr.num = 0; 
    hdr.id = 0; 
    hdr.type = 21845; 
    memcpy((void *) str, (void *) &hdr, sizeof(hdr)); 
    printf("STR: %s\n", str); 

    free(str); 
    return 0; 
} 

上执行它,我看到的只是 “STR”。 str指向的内存区域也没有任何东西可见。

(gdb) b 23 
Breakpoint 1 at 0x8048494: file memcpy.c, line 23. 
(gdb) run 
Starting program: /home/a.out 

Breakpoint 1, main (argc=1, argv=0xbffff234) at memcpy.c:23 
23  memcpy((void *) str, (void *) &hdr, sizeof(hdr)); 
(gdb) n 
24  printf("STR: %s\n", str); 
(gdb) n 
STR: 
26  free(str); 
(gdb) info locals 
hdr = {num = 0, id = 0, type = 21845} 
str = 0x804b008 "" 

我哪里错了?

谢谢!

回答

2

当您指定%s时,printf需要以null结尾的字符串。它不能分辨出你分配了18个字节,而你想要打印这些字节的内容。它看起来在*str,看到一个空字节,并停止寻找。

+0

是的,这是正确的,但为什么由str指出的内存区域为空(在gdb跟踪中)? – hdnivara

+0

@ F430:因为GDB也期待一个以null结尾的字符串。 – user2357112

+0

@ ^:那我怎么能看到内存里有什么?我想我不能使用str,因为它是一个char * – hdnivara

1

str是一个字符串(char *终止于'\0')和hdr是一个结构,它甚至没有字符串字段。如果要将hdr转换为可读的字符串,则必须使用printfsprintf以及适当的转换说明符。

+0

我只是想要数据移动,实际上并没有试图使hdr成为一个字符串。 – hdnivara

+0

在这种情况下,您应该将其复制到另一个'tmp_str'中... –

1

那么,你设置了hdr.num = 0;,所以复制的内存块的第一个字节等于0,所以你的字符串的第一个字符是NULL,这表示它的结束,所以什么都不打印。

2

您的数据正在移动。如果你声明:

tmp_str* str2 = (tmp_str*)str; 

那么它会在调试器中正确显示。你只是看错了数据 - 你的代码正在正确执行。

2

正如所指出的,由于str的第一个字节是'\0'。一个简单的printf("%s",str);语句将不会执行任何操作(它将停止在指示“字符串结束”的第一个字节处)。相反,你可以尝试

int ii; 
printf("STR in hex:\n"); 
for(ii = 0; ii < sizeof(hdr); ii++) { 
    printf("%02x ", str[ii]); 
} 
printf("\n"); 

现在,这将在str为十六进制数字打印的每一个字节;你会看到复制过程正常。

如果你愿意,你可以用

int ii; 
printf("STR in hex:\n"); 
for(ii = 0; ii < sizeof(hdr); ii++) { 
    printf("%c", str[ii]); 
} 
printf("\n"); 

代替这一点,你就会看到实际的字符(但其中一些可能是“不可打印的”,并有可能在终端意想不到的副作用)。