memcpy字符变成了乱码

hzfushi 2009-07-01 04:49:27


struct A
{
char *str;
};

typedef struct A TypeA

void fun(void *p)
{
TypeA b;
b.str = "Turn";
memcpy((unsigned char*)p,¶m,sizeof(TypeA));
}


我在使用上面的代码时,执行完后,p指向的存储单元的字符变成了乱码,请问是什么原因。
...全文
851 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
文刀劉Michael 2009-07-02
  • 打赏
  • 举报
回复
回帖是好事
todaylxp 2009-07-02
  • 打赏
  • 举报
回复
1.p很有可能没有初始化
2.拷贝的长度不对,应该是strlen(b.str)
所以,未被拷贝所覆盖的内存保留了初始值,显示是乱码
goodname 2009-07-02
  • 打赏
  • 举报
回复 1
[Quote=引用 12 楼 tanadar 的回复:]
引用 6 楼 goodname 的回复:
memcpy(temp, b.str, strlen(b.str)+1);//多拷贝一个字节就行。

吹毛求疵,咋不说用strcpy呢?这个更直接。
[/Quote]

楼主给出的代码中使用的是memcpy,人家也许就想用这个方法来实现呢?我这么说只是想尽量贴近他的原文,而不是改变。
breezes2008 2009-07-01
  • 打赏
  • 举报
回复
memcpy((unsigned char*)p,¶m,sizeof(TypeA));//浅拷贝,只是拷贝指针的值。
tanadar 2009-07-01
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 goodname 的回复:]
memcpy(temp, b.str, strlen(b.str)+1);//多拷贝一个字节就行。

[/Quote]吹毛求疵,咋不说用strcpy呢?这个更直接。
Fleeboy 2009-07-01
  • 打赏
  • 举报
回复
顶9楼的
ware_soft 2009-07-01
  • 打赏
  • 举报
回复
看不懂。
nosxcy 2009-07-01
  • 打赏
  • 举报
回复
memcpy((unsigned char*)p,¶m,sizeof(TypeA));
你把param的地址copy 到p指向的内存了,而没把param的内容copy过去,

PS:顶6楼的
wanggang_0717 2009-07-01
  • 打赏
  • 举报
回复
guanzhu
hai040 2009-07-01
  • 打赏
  • 举报
回复
fun改不了p
void fun(void** pp)
goodname 2009-07-01
  • 打赏
  • 举报
回复
memcpy(temp, b.str, strlen(b.str)+1);//多拷贝一个字节就行。
tanadar 2009-07-01
  • 打赏
  • 举报
回复
#include <stdio.h>
#include <string.h>

struct A
{
char *str;
};

typedef struct A TypeA;

void fun(void *p)
{
TypeA b;
unsigned char *temp = (unsigned char*)p;
b.str = "Turn";
memcpy(temp, b.str, strlen(b.str));
temp[strlen(b.str)] = 0;
}

main()
{
unsigned char dst[32];
fun(dst);
printf("%s\n", dst);
}
HelloDan 2009-07-01
  • 打赏
  • 举报
回复
num
Number of bytes to copy.


¶m 这个哪来?

sizeof(TypeA)---> strlen(b.str);
mengjfu 2009-07-01
  • 打赏
  • 举报
回复
p指向那啊?
还是用数组或动态分配吧
goodname 2009-07-01
  • 打赏
  • 举报
回复
结构体A里面的str是一个指针变量,在32为系统上只是4个字节而已。你的sizeof(TypeA)就是4.
你拷贝的并不是str字符串的内容。而是将指针的值拷贝走了。
HelloDan 2009-07-01
  • 打赏
  • 举报
回复
void * memcpy ( void * destination, const void * source, size_t num );



<cstring>

Copy block of memory

Copies the values of num bytes from the location pointed by source directly to the memory block pointed by destination.

The underlying type of the objects pointed by both the source and destination pointers are irrelevant for this function; The result is a binary copy of the data.

The function does not check for any terminating null character in source - it always copies exactly num bytes.

To avoid overflows, the size of the arrays pointed by both the destination and source parameters, shall be at least num bytes, and should not overlap (for overlapping memory blocks, memmove is a safer approach).

Parameters

destination
Pointer to the destination array where the content is to be copied, type-casted to a pointer of type void*.
source
Pointer to the source of data to be copied, type-casted to a pointer of type void*.
num
Number of bytes to copy.



Return Value
destination is returned.

明显是你用得不对。
C++面试题 参考:http://blog.csdn.net/Ghost90/archive/2009/04/22/4099672.aspx 整理:松鼠 时间:2009-5-8 1、const 有什么用途?(请至少说明两种) 答: (1)可以定义 const 常量 (2)const可以修饰函数的参数、返回值,甚至函数的定义体。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。 2、在C++ 程序中调用被 C编译器编译后的函数,为什么要加 extern “C”? 答:C++语言支持函数重载,C语言不支持函数重载。函数被C++编译后在库中的名字与C语言的不同。假设某个函数的原型为: void foo(int x, int y); 该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。 C++提供了C连接交换指定符号extern“C”来解决名字匹配问题。 3、请简述以下两个for循环的优缺点(5分) for (i=0; i乱码。 因为GetMemory返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但其原现的内容已经被清除,新内容不可知。 void GetMemory2(char **p, int num) { *p = (char *)malloc(num); } void Test(void) { char *str = NULL; GetMemory(&str, 100); strcpy(str, "hello"); printf(str); } 请问运行Test函数会有什么样的结果? 答: (1)能够输出hello (2)内存泄漏 void Test(void) { char *str = (char *) malloc(100); strcpy(str, “hello”); free(str); if(str != NULL) { strcpy(str, “world”); printf(str); } } 请问运行Test函数会有什么样的结果? 答:篡改动态内存区的内容,后果难以预料,非常危险。 因为free(str);之后,str成为野指针, if(str != NULL)语句不起作用。 5、编写strcpy函数(10分) 已知strcpy函数的原型是 char *strcpy(char *strDest, const char *strSrc); 其中strDest是目的字符串,strSrc是源字符串。 (1)不调用C++/C的字符串库函数,请编写函数 strcpy char *strcpy(char* strDest, const char* strSrc) { assert((strDest!=NULL) && (strSrc !=NULL));//2分 char *address = strDest;//2分 while( (*strDest++ = * strSrc++) != ‘\0’ )//2分 NULL; return address;// 2分 } 5.1 strcpy能把strSrc的内容复制到strDest,为什么还要char * 类型的返回值? 答:为了实现链式表达式。 // 2分 例如int length = strlen( strcpy( strDest, "hello world") ); 6、编写类String的构造函数、析构函数和赋值函数(25分) 已知类String的原型为: class String { public: String(const char *str = NULL);//普通构造函数 String(const String &other);//拷贝构造函数 ~ String(void);// 析构函数 String & operate =(const String &other);// 赋值函数 private: char* m_data;// 用于保存字符串 }; 请编写String的上述4个函数。 标准答案: // String的析构函数 String::~String(void) // 3分 { delete [] m_data; // 由于m_data是内部数据类型,也可以写成delete m_data; } // String的普通构造函数 String::String(const char *str) // 6分 { if(str==NULL) { m_data = new char[1]; // 若能加NULL 判断则更好 *m_data = ‘\0’; } else { int length = strlen(str); m_data = new char[length+1]; // 若能加NULL 判断则更好 strcpy(m_data, str); } } // 拷贝构造函数 String::String(const String &other) // 3分 { int length = strlen(other.m_data); m_data = new char[length+1]; // 若能加NULL 判断则更好 strcpy(m_data, other.m_data); } // 赋值函数 String & String::operate =(const String &other) // 13分 { // (1) 检查自赋值 // 4分 if(this == &other) return *this; // (2) 释放原有的内存资源 // 3分 delete [] m_data; // ()分配新的内存资源,并复制内容// 3分 int length = strlen(other.m_data); m_data = new char[length+1]; // 若能加NULL 判断则更好 strcpy(m_data, other.m_data); // ()返回本对象的引用 // 3分 return *this; } 7、实现双向链表删除一个节点P,在节点P后插入一个节点,写出这两个函数。 void DeleteNode(DuNode *p) { p->prior->next=p->next; p->next->prior=p->prior; } void InsertNode(DuNode *p, DuNode *s)//Node "s" is inserted after "p" { s->next=p->next; p->next->prior=s; p->next=s; s->prior=p; } 8、Windows程序的入口是哪里?写出Windows消息机制的流程。 WINDOWS入口是WinMain函数 消息机制的流程: 系统中发生了某个事件 Windows把这个事件翻译为消息,然后把它放到消息队列中 1. 应用程序从消息队列中接收到这个消息,把它存放在TMsg记录中 2. 应用程序把消息传递给一个适当的窗口的窗口过程 3. 窗口过程响应这个消息并进行处理 9.写一个函数,将其中的\t都转换成4个空格。 #include using namespace std; char* Convert_t(char *des,char *src) { char *temp; des=new char[100]; temp=des; while(*src!='\0') { if(*src=='\t') { src++; *des++=' '; *des++=' '; *des++=' '; *des++=' '; continue; } *des++=*src++; } *des='\0'; des=temp; return des; } int main() { char *t="asdf\tasd\tasasddas\\tdfasdf",*d; cout< using namespace std; char *des=new char[100]; //全局变量的动态空间申请在程序运行之后,main运行之前完成。所以不是所有的动作都是main引起的。 int main() { char *des="abc"; cout<字符串循环右移n个。比如原来是“abcdefghi”如果n=2,移位后应该是“hiabcdefgh” 正确解答1: void LoopMove(char* pStr, int steps) { int n = strlen( pStr ) - steps; char tmp[MAX_LEN]; strcpy ( tmp, pStr + n ); strcpy ( tmp + steps, pStr); *( tmp + strlen ( pStr ) ) = '\0'; strcpy( pStr, tmp ); } 正确解答2: void LoopMove(char* pStr,int steps ) { int n = strlen( pStr ) - steps; char tmp[MAX_LEN]; memcpy( tmp, pStr + n, steps ); memcpy(pStr + steps, pStr, n ); memcpy(pStr, tmp, steps ); } 14、写出输出结果 void fun(char s[10]) { char a[10]; cout<<"a:"< main() { int a,b,c,d; a=10; b=a++; c=++a; d=10*a++; printf("b,c,d:%d,%d,%d",b,c,d); return 0; } 答:10,12,120 main() { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1); printf("%d,%d",*(a+1),*(ptr-1)); } 输出:2,5 *(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5 &a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int) int *ptr=(int *)(&a+1); 则ptr实际是&(a[5]),也就是a+5 原因如下: &a是数组指针,其类型为 int (*)[5]; 而指针加1要根据指针类型加上一定的值, 不同类型的指针+1之后增加的大小不同 a是长度为5的int数组指针,所以要加 5*sizeof(int) 所以ptr实际是a[5] 但是prt与(&a+1)类型是不一样的(这点很重要) 所以prt-1只会减去sizeof(int*) a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5]

70,037

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧