结构体copy问题
c语言中,结构使用是非常频繁的,操作结构体时,我们一般使用memcpy对结构体进行copy赋值,其实我们忽略了一点,同一种类型结构体是可以直接进行赋值的。另外,本文介绍下使用memcpy copy结构体时的一些注意事项。
一.结构体内存对齐
使用memcpy对结构体进行内存copy,首先要知道结构体的大小计算,最简单的方法使用sizeof(结构体类型)进行计算。当然,本文也介绍下结构体所占空间大小计算方法。
主要有两原则:
1.对结构体成员进行存储时,要以自身为起始地址(相对地址),每个成员存放到地址要是自身大小的整数倍。
例如:(4+4+8)
#include<stdio.h>
typedef struct test
{
char a;
int b;
double c;
}test_t;
int main(int argc, const char *argv[])
{
test_t a;
printf("sizeof:%d\n",(int)sizeof(test_t));
return 0;
}
2.计算出来的结构体总大小要为其成员最大宽度的整数倍
例如:(8+8+8)
#include<stdio.h>
typedef struct test
{
char a;
double c;
int b;
}test_t;
int main(int argc, const char *argv[])
{
test_t a;
printf("sizeof:%d\n",(int)sizeof(test_t));
return 0;
}
二.结构体copy
使用memcpy对结构体进行内存拷贝,归根到底就是将内存的数据从一个地址复制到另一个地址上。
先贴上测试代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//无指针结构体
typedef struct test
{
char str[16]; //name
char s; //sex
int m; //age
}test_t;
//有指针结构体
typedef struct tests
{
test_t * atest;
char job[20];
}tests_t;
//结构体成员定义存在差异
typedef struct testn
{
char str[20]; //name
char s; //sex
int m; //age
}testn_t;
int main(int argc, const char *argv[])
{
//测试1
test_t nab1,nab2,nab3;
strcpy(nab1.str,"tom");
nab1.s = 'm';
nab1.m = 20;
memcpy(&nab2,&nab1,sizeof(test_t));
nab3 = nab1;
printf("nab1.name:%s,nab1.sex:%c,nab1.age:%d\n",nab1.str,nab1.s,nab1.m);
printf("nab2.name:%s,nab2.sex:%c,nab2.age:%d\n",nab2.str,nab2.s,nab2.m);
printf("nab3.name:%s,nab3.sex:%c,nab3.age:%d\n",nab3.str,nab3.s,nab3.m);
//测试二
tests_t nabs1,nabs2,nabs3;
nabs1.atest = &nab1;
strcpy(nabs1.job,"teacher");
memcpy(&nabs2,&nabs1,sizeof(tests_t));
nabs3 = nabs1;
printf("%s,%c,%d,%s\n",nabs1.atest->str,nabs1.atest->s,nabs1.atest->m,nabs1.job);
printf("%s,%c,%d,%s\n",nabs2.atest->str,nabs2.atest->s,nabs2.atest->m,nabs2.job);
printf("%s,%c,%d,%s\n",nabs3.atest->str,nabs3.atest->s,nabs3.atest->m,nabs3.job);
//测试三
printf("test_t:%d,testn_t:%d\n",(int)sizeof(test_t),(int)sizeof(testn_t));
testn_t nabn;
nabn.m=8;
memcpy(&nabn,&nab1,sizeof(test_t));
printf("nab1.name:%s,nab1.sex:%c,nab1.age:%d\n",nabn.str,nabn.s,nabn.m);
printf("nab1.name:%s,nab1.sex:%d,nab1.age:%d\n",nabn.str,nabn.s,nabn.m);
return 0;
}
编译运行:
测试一:
对于同一种类型的结构体,内存拷贝与结构体直接赋值是等价的,至少在本例中等价。
测试二:
如果结构体中存在指针变量,其大小就是四个字节,并不影响结构体直接赋值或者使用memcpy。
测试三:
对于不同类型的结构体进行拷贝,会出现什么问题。
现在有test_t,testn_t两种类型的结构体,从log看test_t 占24个字节,testn_t占28个字节大小,实际计算也是如此。现在将test_t类型的结构体copy到testn_t类型的结构体,会出现什么结果。
由上图可以看出,直接内存拷贝。
由测试三最后一条log,可以看出,与上图是对应的,至于字符串打印没变,是因为%s打印遇到’\0’结束,我们也可以做个测试。
#include<stdio.h>
int main(int argc, const char *argv[])
{
char str[20] ="12345678a\0 555";
char string[20] = "123456789a 555";
printf("str:%s\nstring:%s\n",str,string);
return 0;
}
编译运行