溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

C語(yǔ)言結(jié)構(gòu)體強(qiáng)制轉(zhuǎn)換的方法

發(fā)布時(shí)間:2021-08-12 14:20:36 來(lái)源:億速云 閱讀:1150 作者:chen 欄目:編程語(yǔ)言

這篇文章主要講解了“C語(yǔ)言結(jié)構(gòu)體強(qiáng)制轉(zhuǎn)換的方法”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“C語(yǔ)言結(jié)構(gòu)體強(qiáng)制轉(zhuǎn)換的方法”吧!

在C語(yǔ)言中,結(jié)構(gòu)體無(wú)法用以下方式強(qiáng)制轉(zhuǎn)換:

Struct_B b;
Struct_A a = (Struct_A)b;

但可以使用指針間接轉(zhuǎn)換:

Struct_B *b;
Struct_A *a = (Struct_A *)b;

很明顯,這樣強(qiáng)行給指針賦值,容易出現(xiàn)異常。讓我們來(lái)做一下測(cè)試。

先定義4個(gè)結(jié)構(gòu)體

typedef struct {
    int array[4];
}Struct_A;

typedef struct {
    int *ptr_b;
} Struct_B;

typedef struct {
    int int1;
    int int_array1[2];
    float float_array2[2];
}Struct_C;

typedef struct{
    char char1;
    char char_array[2];
}Struct_D;

然后進(jìn)行轉(zhuǎn)換測(cè)試

void main(){
    //先對(duì)定義Struct_A變量a
    Struct_A *a = malloc(sizeof(Struct_A));
    if(a==NULL){return;};
    int temp_a[4] = {0,1,2,3};
    memcpy(a->array, &temp_a, 4*sizeof(int));
    
    //將指針a賦值給b, c, d
    Struct_B *b = (Struct_B *)a;
    Struct_C *c = (Struct_C *)a;
    Struct_D *d = (Struct_D *)a;

    //打印一些重要的長(zhǎng)度作為參考
    printf("The system bits is %d\n", __WORDSIZE);
    printf("The Size of int: %d Byte\nThe Size of int poniter: %d Byte\n", sizeof(int), sizeof(int*));
    printf("The Size of float: %d Byte\n", sizeof(float));
    printf("The Size of char: %d Byte\nThe Size of char pointer: %d Byte\n", sizeof(char),  sizeof(char*));

    //打印賦值結(jié)果
    print_all_struct(a,b,c,d);
    printf_a(a);
    printf_b(b);
    printf_c(c);
    printf_d(d);
    return;
}

輸出(注釋為后期添加)為:

The system bits is 64
The Size of int: 4 Byte     #64 位系統(tǒng)int占4個(gè)字節(jié)
The Size of int poniter: 8 Byte     #64 位系統(tǒng)指針占8字節(jié)
The Size of float: 4 Byte   #64 位系統(tǒng)float占4字節(jié)
The Size of char: 1 Byte    #64 位系統(tǒng)char占1個(gè)字節(jié)
The Size of char pointer: 8 Byte     #64 位系統(tǒng)指針占8字節(jié)

Show points    #四個(gè)結(jié)構(gòu)體的指針相等,說(shuō)明指針賦值成功
 ------------------------------------------------------------------------
|Pointer of a     |Pointer of b     |Pointer of c     |Pointer of d     |
 ------------------------------------------------------------------------
|0x5555555592a0   |0x5555555592a0   |0x5555555592a0   |0x5555555592a0   |
 ------------------------------------------------------------------------
Struct_A:    #包含一個(gè)數(shù)組array[4]
0x5555555592a0: a->array[0] = 0    #結(jié)構(gòu)體中第1個(gè)元素(array)起始地址與結(jié)構(gòu)體指針(a)相等
0x5555555592a4: a->array[1] = 1    #結(jié)構(gòu)體指針(a)+int長(zhǎng)度(4字節(jié)) 得array中第2個(gè)元素地址
0x5555555592a8: a->array[2] = 2    #結(jié)構(gòu)體指針(a)+int長(zhǎng)度(4字節(jié))*2 得array中第3個(gè)元素地址
0x5555555592ac: a->array[3] = 3

Struct_B:    #包含一個(gè)int指針ptr_b
&(b->ptr_b): 0x5555555592a0    #結(jié)構(gòu)體中第1個(gè)元素int指針ptr_b的 地址 等于結(jié)構(gòu)體指針(b)
b->ptr_b: 0x100000000   #是地址相等,而不是值相等,要注意區(qū)分。沒(méi)有為指針ptr_b分配內(nèi)存,故地址為0x100000000

Struct_C:
0x5555555592a0: c->int1: 0    #第1個(gè)元素地址等于指針c,該地址有值,元素類(lèi)型與內(nèi)存的值中一致,"賦值"成功
0x5555555592a4: c->int_array1[0]: 1    #指針c+int長(zhǎng)度(4字節(jié))得到元素 c->int_array1[0]的地址,該地址有值,值類(lèi)型與內(nèi)存的值中一致,"賦值"成功
0x5555555592a8: c->int_array1[1]: 2    #指針c+int長(zhǎng)度(4字節(jié))*2剛好是 c->int_array1[1]的起始地址,該地址有值,值類(lèi)型與內(nèi)存的值中一致,"賦值"成功
0x5555555592ac: c->float_array2[0]: 0.000000  #地址有值,但類(lèi)型不是float,”賦值“失敗
0x5555555592b0: c->float_array2[1]: 0.000000  #這個(gè)地址沒(méi)有值,float默認(rèn)值為0.000000

Struct_D:
0x5555555592a0: d->char1: (null)    #第1個(gè)元素地址等于指針d, 但值的類(lèi)型與內(nèi)存中不同,”賦值“失敗
0x5555555592a1: d->char_array[0]: (null)    #值的類(lèi)型不同,導(dǎo)致長(zhǎng)度不同,得到的地址中無(wú)值
0x5555555592a2: d->char_array[1]: (null)    #同上

我們先來(lái)看輸出結(jié)果的圖解: C語(yǔ)言結(jié)構(gòu)體強(qiáng)制轉(zhuǎn)換的方法

從上面的結(jié)果我們可以得出幾個(gè)結(jié)論:

  1. 結(jié)構(gòu)體指針等于第一個(gè)元素的起始地址

如果第一個(gè)元素是指針p,請(qǐng)注意是指針變量的地址&p,而不是指針本身p

  1. 結(jié)構(gòu)體內(nèi)的元素在內(nèi)存中順序排列,賦值時(shí)也是順序”賦值“。滿(mǎn)足兩個(gè)條件即可”賦值“成功:

    • 元素起始地址上有值

    • 元素類(lèi)型與內(nèi)存中的值類(lèi)型一致

嚴(yán)格來(lái)說(shuō)其實(shí)并不是賦值,而是指定了結(jié)構(gòu)體的起始地址,根據(jù)元素的長(zhǎng)度可以順序得到各個(gè)元素的地址,如果元素地址上有值,且元素類(lèi)型與內(nèi)存中的值一致,則可以直接使用,否則無(wú)法使用,自動(dòng)轉(zhuǎn)為默認(rèn)值。

補(bǔ)充: 到這里有的讀者可能會(huì)問(wèn),內(nèi)存中并沒(méi)有存儲(chǔ)數(shù)據(jù)類(lèi)型,為什么筆者一直在強(qiáng)調(diào)元素類(lèi)型與內(nèi)存中的值類(lèi)型是否一致呢?

原因是不同類(lèi)型的值在內(nèi)存中的編碼存儲(chǔ)方式不一樣,一個(gè)按int編碼值是無(wú)法按float方式直接讀取的。詳細(xì)原理此處不再贅述。

最后附上完整代碼

#include <stdio.h>
#include <malloc.h>
#include <bits/wordsize.h>

typedef struct {
    int array[4];
}Struct_A;

typedef struct {
    int *ptr_b;
} Struct_B;

typedef struct {
    int int1;
    int int_array1[2];
    float float_array2[2];
}Struct_C;

typedef struct{
    char char1;
    char char_array[2];
}Struct_D;

void printf_a(Struct_A *a){
    printf("Struct_A:\n");
    for(int i=0; i<4; i++){
        printf("%p: a->array[%d] = %d\n", &((a->array)[i]), i, (a->array)[i]);
    }
}

void printf_b(Struct_B *b){
    printf("Struct_B:\n");
    printf("&(b->ptr_b): %p\n",&(b->ptr_b));
    printf("b->ptr_b: %p\n", b->ptr_b); 
}

void printf_c(Struct_C *c){
    printf("Struct_C:\n");
    printf("%p: c->int1: %d\n", &(c->int1), c->int1);
    printf("%p: c->int_array1[0]: %d\n", &(c->int_array1[0]), c->int_array1[0]);
    printf("%p: c->int_array1[1]: %d\n", &(c->int_array1[1]), c->int_array1[1]);   
    printf("%p: c->float_array2[0]: %f\n", &(c->float_array2[0]), c->float_array2[0]);  
    printf("%p: c->float_array2[1]: %f\n", &(c->float_array2[1]), c->float_array2[1]);   
}

void printf_d(Struct_D *d){
    printf("Struct_D:\n");
    printf("%p: d->char1: %s\n", &(d->char1), d->char1);
    printf("%p: d->char_array[0]: %s\n", &(d->char_array[0]), d->char_array[0]);
    printf("%p: d->char_array[1]: %s\n", &(d->char_array[1]), d->char_array[1]);    
}

void print_all_struct(Struct_A *a, Struct_B *b, Struct_C *c, Struct_D *d){
    printf("Show points\n");
    printf(" -----------------------------------------------------------------------\n");
    printf("|Pointer of a     |Pointer of b     |Pointer of c     |Pointer of d     |\n");
    printf(" -----------------------------------------------------------------------\n");
    printf("|%p   |%p   |%p   |%p   |\n", a, b, c, d);
    printf(" -----------------------------------------------------------------------\n");  
}

void main(){
    Struct_A *a = malloc(sizeof(Struct_A));
    if(a==NULL){return;};
    int temp_a[4] = {0,1,2,3};
    memcpy(a->array, &temp_a, 4*sizeof(int));

    Struct_B *b = (Struct_B *)a;
    Struct_C *c = (Struct_C *)a;
    Struct_D *d = (Struct_D *)a;

    printf("The system bits is %d\n", __WORDSIZE);
    printf("The Size of int: %d Byte\nThe Size of int poniter: %d Byte\n", sizeof(int), sizeof(int*)); 
    printf("The Size of float:%d\n",sizeof(float));
    printf("The Size of char: %d Byte\nThe Size of char pointer: %d Byte\n", sizeof(char),  sizeof(char*));
    print_all_struct(a,b,c,d);

    printf_a(a);
    printf_b(b);
    printf_c(c);
    printf_d(d);
    return;
}

感謝各位的閱讀,以上就是“C語(yǔ)言結(jié)構(gòu)體強(qiáng)制轉(zhuǎn)換的方法”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)C語(yǔ)言結(jié)構(gòu)體強(qiáng)制轉(zhuǎn)換的方法這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI