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-arith
flag 가 지정되어 있습니다(이 플래그는 코드 베이스가 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
void
type은 빈 값 세트로 구성됩니다.완료할 수 없는 불완전한 오브젝트 유형입니다.
다음 프로그램은 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+1
sizeof(int)
는 바이트로 , 포인터는 바이트로 이동, 포인터는 바이트로 이동x + sizeof(int)
(float*)x+1
sizeof(float)
바이트 등
첫 번째 아이템은 휴대성이 없고 C/C++의 Galateo에 반대하지만, C-language는 정확합니다.즉, 대부분의 컴파일러에서 적절한 플래그가 필요한 것으로 컴파일 됩니다(Wpointer-alse 등).
언급URL : https://stackoverflow.com/questions/3523145/pointer-arithmetic-for-void-pointer-in-c
'programing' 카테고리의 다른 글
Android Studio 및 Gradle에서 소스 1.7을 설정하는 방법 (0) | 2022.08.28 |
---|---|
찾을 수 없는 키에 대한 기본값을 반환하려면 HashMap을 선택하십시오. (0) | 2022.08.28 |
정적 필드와 함께 @Autowired를 사용할 수 있습니까? (0) | 2022.08.28 |
0.1을 여러 번 더하는 것은 왜 무손실인 채로 남습니까? (0) | 2022.08.28 |
오른쪽 정렬 버튼 그룹 Vuetify (0) | 2022.08.28 |