programing

C의 보이드 포인터에 대한 포인터 산술

goodcopy 2022. 8. 28. 18:53
반응형

C의 보이드 포인터에 대한 포인터 산술

특정 유형에 대한 포인터가 있는 경우(예:int,char,float, ..)이 증분되고, 그 값은 해당 데이터 유형의 크기만큼 증가합니다.만약 a가void크기의 데이터를 가리키는 포인터x증가됩니다. 어떻게 하면 이 포인트와x바이트 전방에?컴파일러가 추가 방법을 어떻게 알 수 있습니까?x포인터의 값을 매길까요?

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

GCC는 이를 확장으로 허용합니다( 섹션은 설명서의 "C 확장" 장의 일부입니다).Clang 및 ICC는 다음을 허용합니다.void*GCC와의 호환성을 목적으로 한 산술.다른 컴파일러(MSVC 등)에서는 연산 기능을 사용할 수 없습니다.void*및 GCC는, 다음의 경우, 그것을 허가하지 않습니다.-pedantic-errors플래그가 지정되어 있거나-Werror-pointer-arithflag 가 지정되어 있습니다(이 플래그는 코드 베이스가 MSVC 와 컴파일 할 필요도 있는 경우에 편리합니다).

C 스탠다드

인용문은 n1256 초안에서 인용한 것입니다.

이 표준의 추가 조작에 대한 설명은 다음과 같습니다.

6.5.6-2: 또한, 두 피연산자 중 하나는 산술형이어야 하며, 한 피연산자는 물체형식의 포인터여야 하며, 다른 한 피연산자는 정수형이어야 한다.

자, 여기서의 질문은,void*'개체 유형'에 대한 포인터 또는 동등한 포인터입니다.void는 "오브젝트 타입"입니다."개체 유형"의 정의는 다음과 같습니다.

6.2.5.1: 타입은 오브젝트 타입(오브젝트를 완전하게 기술하는 타입), 기능 타입(기능을 기술하는 타입), 불완전한 타입(오브젝트를 기술하는 타입이지만 사이즈를 결정하는 데 필요한 정보가 부족한 타입)으로 분할됩니다.

그리고 이 표준은 다음과 같이 정의한다.void다음과 같이 합니다.

6.2.5-19: 유형은 빈 값 집합으로 구성됩니다. 완료할 수 없는 불완전한 유형입니다.

부터void는 불완전한 타입이며 오브젝트 타입이 아닙니다.따라서 추가 작업에 유효한 오퍼랜드가 아닙니다.

따라서 포인터 연산을 실행할 수 없습니다.void포인터

메모들

당초에는 이라고 생각되었다void*C 표준의 다음 섹션 때문에 산술이 허용되었다.

6.2.5-27: 보이드에 대한 포인터는 문자 형식에 대한 포인터와 동일한 표현정렬 요건을 가져야 한다.

하지만,

동일한 표현정렬 요건은 함수에 대한 인수, 함수의 반환 값 및 조합의 구성원과 같은 상호 호환성을 암시하는 것을 의미한다.

, ②,printf("%s", x) 뜻을 x은 ★★★★★★★★★★★★★char* ★★★★★★★★★★★★★★★★★」void*를 할 수 void*.

되지 않습니다.void*포인터

그것을 char 포인터에 던져 x바이트 앞으로 포인터를 늘립니다.

C 표준은 보이드 포인터 연산을 허용하지 않습니다., GNU C는 void의 크기를 고려하여 허용됩니다.1.

C11 표준 § 6.2.5

패러그래프 - 19

voidtype은 빈 값 세트로 구성됩니다.완료할 수 없는 불완전한 오브젝트 유형입니다.

다음 프로그램은 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 *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 *아, 아, 아, 아!

포인터 연산을 수행하기 전에 다른 유형의 포인터에 해당 포인터를 캐스팅해야 합니다.

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

이유: 포인터 산술은 기본 주소에 대해 발생하므로 일반 산술과 다릅니다.

솔루션:연산 시 유형 캐스트 연산자를 사용합니다. 그러면 포인터 연산을 수행하는 식에 대해 기본 데이터 유형을 알 수 있습니다.ex: 점은 보이드 포인터입니다.

*point=*point +1; //Not valid
*(int *)point= *(int *)point +1; //valid

컴파일러는 유형별 캐스팅을 인식합니다.「」가 됩니다.void *x:

  • x+1를 1 합니다.x는 바이트, 포인터는 바이트로 x+1
  • (int*)x+1sizeof(int)는 바이트로 , 포인터는 바이트로 이동, 포인터는 바이트로 이동x + sizeof(int)
  • (float*)x+1sizeof(float)바이트 등

첫 번째 아이템은 휴대성이 없고 C/C++의 Galateo에 반대하지만, C-language는 정확합니다.즉, 대부분의 컴파일러에서 적절한 플래그가 필요한 것으로 컴파일 됩니다(Wpointer-alse 등).

언급URL : https://stackoverflow.com/questions/3523145/pointer-arithmetic-for-void-pointer-in-c

반응형