[英]Pointer arithmetic for void pointer in C
當指向特定類型(例如int
、 char
、 float
、 ..)的指針遞增時,其值會增加該數據類型的大小。 如果指向大小為x
數據的void
指針遞增,它如何指向前面的x
個字節? 編譯器如何知道將x
添加到指針的值?
最終結論:對void*
算術在 C 和 C++ 中都是非法的。
GCC 允許將其作為擴展,參見 關於void
和函數指針的算術(注意本節是手冊“C 擴展”一章的一部分)。 為了與 GCC 兼容,Clang 和 ICC 可能允許void*
算術。 其他編譯器(例如 MSVC)不允許對void*
算術運算,如果指定了-pedantic-errors
標志,或者指定了-Werror-pointer-arith
標志(如果您的代碼庫也必須用 MSVC 編譯)。
引自 n1256 草案。
該標准對加法運算的描述指出:
6.5.6-2:對於加法,要么兩個操作數都為算術類型,要么一個操作數為指向對象類型的指針,另一個操作數為整數類型。
所以,這里的問題是void*
是否是指向“對象類型”的指針,或者等價地, void
是否是“對象類型”。 “對象類型”的定義是:
6.2.5.1:類型分為對象類型(完整描述對象的類型)、函數類型(描述函數的類型)和不完整類型(描述對象但缺少確定其大小所需的信息的類型)。
該標准將void
定義為:
6.2.5-19:
void
類型包含一組空值; 它是無法完成的不完整類型。
由於void
是不完整的類型,因此它不是對象類型。 因此,它不是加法運算的有效操作數。
因此,您不能對void
指針執行指針運算。
最初,人們認為void*
算術是允許的,因為 C 標准的這些部分:
6.2.5-27:指向 void 的指針應具有與指向字符類型的指針相同的表示和對齊要求。
然而,
相同的表示和對齊要求意味着作為函數的參數、函數的返回值和聯合成員的可互換性。
所以這意味着printf("%s", x)
無論x
類型是char*
還是void*
都具有相同的含義,但這並不意味着您可以對void*
進行算術運算。
void*
指針上不允許進行指針運算。
將其強制轉換為 char 指針,將您的指針向前增加 x 個字節。
C 標准不允許空指針算術。 但是,考慮到void的大小為1
, GNU C是允許的。
C11 標准 §6.2.5
第 19 段
void
類型包含一組空值; 它是無法完成的不完整對象類型。
以下程序在 GCC 編譯器中運行良好。
#include<stdio.h>
int main()
{
int arr[2] = {1, 2};
void *ptr = &arr;
ptr = ptr + sizeof(int);
printf("%d\n", *(int *)ptr);
return 0;
}
可能是其他編譯器產生錯誤。
您不能對void *
類型進行指針運算,正是出於這個原因!
在進行指針運算之前,您必須將其轉換為另一種類型的指針。
空指針可以指向任何內存塊。 因此,當我們嘗試對 void 指針進行指針算術時,編譯器不知道要增加/減少多少字節。 因此,void 指針必須首先被類型轉換為已知類型,然后才能參與任何指針運算。
void *p = malloc(sizeof(char)*10);
p++; //compiler does how many where to pint the pointer after this increment operation
char * c = (char *)p;
c++; // compiler will increment the c by 1, since size of char is 1 byte.
void 指針中不允許進行指針運算。
原因:指針算術與普通算術不同,因為它是相對於基址發生的。
解決方案:在算術時使用類型轉換運算符,這將使執行指針算術的表達式的基本數據類型已知。 例如:point 是空指針
*point=*point +1; //Not valid
*(int *)point= *(int *)point +1; //valid
編譯器通過類型轉換知道。 給定一個void *x
:
x+1
向x
增加一個字節,指針指向字節x+1
(int*)x+1
添加sizeof(int)
個字節,指針指向字節x + sizeof(int)
(float*)x+1
地址sizeof(float)
字節等。盡管第一項是不可移植的,並且與 C/C++ 的 Galateo 背道而馳,但它仍然是 C 語言正確的,這意味着它可以在大多數編譯器上編譯為某些內容,可能需要一個適當的標志(如 -Wpointer-arith)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.