簡體   English   中英

在指針算術中使用 char* over void*

[英]Use of char* over void* in pointer arithmetic

我正在瀏覽此代碼以用於學習目的,並對這一行有疑問:

return (char*)desc + sizeof *desc;

為什么desc轉換為char* 我試圖用我自己的代碼來模仿它:

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

struct Test {
    int value;
};

int main() {

    struct Test* test = malloc(sizeof test);

    struct Test* test1 = (void*)test + sizeof *test;
    test1->value = 1;
    printf("%d\n", test1->value);

    struct Test* test2 = (void*)test1 + sizeof *test;
    test2->value = 10;
    printf("%d\n", test2->value);

}

這也有效。 但是,有什么區別呢? 為什么使用char*

注意:我使用void*只是為了看看它是否有效。 由於char*與所討論的struct無關,我只是想,“如果我在那里使用void*怎么辦?”。 一個更具體的問題可能是,為什么不int*float*以及為什么使用char*

為什么使用指向字符的指針

為什么 desc 轉換為 char*? ...因為char*與所討論的struct無關...

在 C 中,除位域外的每個 object 都由字節序列組成。 1將 object 的地址轉換為char *會生成指向 object 的第一個字節的指針,您可以使用該指針訪問 object 的各個字節。

在標准 C 中,指針運算使用指向類型的單位。 對於struct Test類型的指針pp+1指向 p 之后的下一個結構, p p+2指向之后的結構,依此類推。 對於char *類型的指針qq+1指向 q 之后的下一個charq+2指向之后的char ,依此類推。

因此,要訪問 object 的各個字節,您可以將其地址轉換為char *並使用它。

為什么不使用其他類型的指針

一個更具體的問題可能是,為什么不int*float*以及為什么使用char*

使用char *是因為 C 中的所有對象(位域除外)都被定義為表示為字節序列。 它們不一定是intfloat的序列。 unsigned char *signed char *也可以使用,由於符號問題的復雜性, unsigned char *可能更可取。

C 標准有關於使用字符指針訪問對象的特殊規則,因此它保證以這種方式訪問 object 的字節是可行的。 相反,使用int *float *訪問對象可能不起作用。 允許編譯器期望指向int的指針不會用於訪問float object,並且當它為程序生成機器指令時,它可能會根據該期望編寫這些指令。 使用字符指針可防止編譯器假定char *與另一種指針指向的位置不同。

為什么指向無效工作的指針

注意:我使用void*只是為了看看它是否有效。

為了使指針算法起作用,編譯器需要知道指向的 object 的大小。 將 1 添加到指向struct Test的指針時,編譯器需要知道調整內部地址的字節數。

void是不完整的類型。 沒有void對象,並且void沒有大小。 (大小不為零。沒有大小。)因此,當pvoid *時,C 標准沒有定義p+1的任何含義。

但是, GCC 將void *上的算術定義為擴展 它的工作方式就好像void的大小為 1 個字節。 Clang 也支持這個。

由於這個擴展,使用void *指針進行算術運算與使用char *指針進行算術運算本質上是相同的。

這個擴展是不必要的; 任何對void *進行算術運算的代碼都可以改寫為使用char * 有時這需要額外的強制轉換來轉換指針類型,這可能就是將擴展添加到 GCC 的原因(以減少所需的代碼量並使其看起來更好)。

您可以使用開關-Werror -Wpointer-arith禁用此擴展,或者您通常可以使用-Werror -std=c18 -pedantic 我盡可能使用-Werror -std=c18 -pedantic ,我推薦它。

腳注

1位域是保存在一些較大的字節容器中的位序列,可能恰好與字節重合。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM