結構體copy問題

結構體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;
}

編譯運行
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章