[c] C에서 void 포인터에 대한 포인터 산술

특정 유형 (예 int: char,, float..)에 대한 포인터 가 증가하면 해당 데이터 유형의 크기만큼 값이 증가합니다. 경우 void크기의 데이터에 대한 포인터하는 포인트가 x증가 점에, 어떻게 나올까요 x앞서 바이트? 컴파일러 x는 포인터의 가치 를 높이는 방법을 어떻게 알 수 있습니까?



답변

최종 결론 : a에 대한 산술 void*은 C와 C ++에서 모두 불법 입니다.

GCC는이를 확장으로 허용합니다. 산술 void및 함수 포인터를 참조하십시오 (이 섹션은 설명서의 “C 확장”장의 일부입니다). Clang과 ICC void*는 GCC와의 호환성을 위해 산술을 허용 할 것 입니다. 다른 컴파일러 (MSVC와 같은)는에 대한 산술을 허용하지 void*않으며 GCC는 -pedantic-errors플래그가 지정되거나 플래그가 지정된 경우이를 허용하지 않습니다 -Werror-pointer-arith(이 플래그는 코드베이스도 MSVC로 컴파일해야하는 경우에 유용합니다).

C 표준은 말한다

따옴표는 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)관계없이 동일한 의미를 갖지만,에 대해 산술을 수행 할 수있는 것은 아닙니다 .xchar*void*void*

편집자 주 : 이 답변은 최종 결론을 반영하기 위해 편집되었습니다.


답변

포인터에는 포인터 산술이 허용되지 않습니다 void*.


답변

포인터를 x 바이트 앞으로 앞으로 증가시키는 char 포인터로 캐스트하십시오.


답변

C 표준은 허용하지 않습니다 무효 포인터 연산을. 그러나, GNU C는 의 크기를 고려하여 허용 무효 IS를 1.

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.