void가 알려지지 않은 크기가있을 때 포인터 산술 [닫기
-
16-09-2019 - |
문제
Visual Studio C ++ 버전 9 (및 기타 버전도)에서 다음 코드입니다.
int a = sizeof(void);
void const *b = static_cast<void const *>("hello world");
b += 6;
error C2070: 'void': illegal sizeof operand
error C2036: 'const void *' : unknown size
이 코드는 처리하는 GCC에서 작동합니다 sizeof(void)
~처럼 1
.
명시 적으로 캐스팅하는 것처럼이 제한을 중심으로 어떤 방법이 있습니까? char *
포인터 산술의 목적 상 혼란에 추가됩니다 (void *
잘 인식되고 원시 메모리에 대한 유형이없는 포인터로 사용됩니다).
업데이트 0
- 표준의 존재를 잘 알고 있습니다.
- 나 원하다 원시 포인터 산술을 수행합니다.
- 나는 가져 간다
sizeof(void)
내가 그렇지 않다는 사실을 잘 알고 있음을 보여주기 위해1
문제의 원인입니다. - 코드 예제는 단순히 오류를 생성하는 데 필요한 것을 보여주는 것입니다.
- 나는 이것이 "정상적인"사용 방법이 아니라는 것을 알고 있습니다.
void
, 그러나 이것은 C이고, 이런 일이 일어납니다. - 예, 사람들은 저수준 에서이 작업을 수행해야합니다. 나는 왜 그런지, 나는 어떻게 지내고있다. 이유를 알고 싶다면 커널 소스 또는 친절한 glibc를 살펴보십시오.
업데이트 1
이 질문이 많은 혼란을 일으킨 것 같습니다. 문제는 아닙니다 왜 was sizeof(void) == 1
표준이 아니라 그렇지 않을 때해야 할 일입니다.
단일 바이트 포인터 산술이 수행 될 예정인 경우 캐스팅이 char *
정답이 아닙니다 *(void *)
크기는 없지만 표준은 실제로 *(char *)
항상 1
. 따라서 사용 char *
항상 정확하고 일치합니다 void *
원시 포인터 산술의 목적 상 GCC 확장 기능.
요점을 더욱 강화하기 위해 void *
타이핑없는 메모리에 대한 포인터가 올바른 선택이며 char *
캐스트하기에 올바른 유형입니다 원시 포인터 산술 용.
해결책 8
그것은 보일 것입니다 정답 사용하는 것입니다 char *
포인터 산술의 경우 sizeof(char)
항상 1 개로 정의되며 모든 플랫폼에서 가장 훌륭한 주소로 된 세분화로 정의됩니다.
요컨대, 한계를 중심으로 방법이 없습니다. char *
실제로 올바른 방법입니다.
Matthias Wandel 그랬어 정답 그러나 다른 정당화와 함께.
다른 팁
포인터를 늘리는 것은 기술적으로 가리키는 것의 크기로 인해 그것을 증가시켜야합니다. 무효 점은 아무것도 없으므로 크기는 알려져 있지 않습니다.
일부 컴파일러가 공간 포인터를 증가시킬 수 있도록하는 것은 냉담한 일입니다.
캐스팅은 다른 포인터에 캐스팅 한 다음 뒤로 물러나거나 어색한 일을해야하기 때문에 성가신 일입니다. (*(char *)&voidptr) += 6
개인적으로, 나는 그것을 a라고 선언합니다 char *
산술 목적 상
C 언어로 sizeof
불완전한 유형에 적용 할 수 없습니다. void
불완전한 유형이므로 오페라로 사용할 수 없습니다. sizeof
.
포인터 산술의 void *
포인터는 C에서도 지원되지 않습니다. 포인터 산술과 함께 사용하려면 포인터는 객체 유형을 가리켜 야합니다. void
아니다.
GCC는 이상한 언어 확장으로 허용합니다.
void *
"알 수없는 포인터"를 암시하기위한 것입니다.
따라서 공허 포인터에 6을 추가하는 것은 정의되지 않습니다. 컴파일러에게 "알 수없는 객체의 크기"로 포인터를 전진 시키도록 요청하기 때문입니다.
당신은 그것을하지 말아야합니다.
여기에는 두 가지 질문이 있습니다. 첫 번째는 void
, 두 번째 void*
. 그것들은 다른 유형이며 이름 옆에 공통점이 거의 없습니다.
void
주로 함수 선언/정의에 사용됩니다 (반환 유형 또는 "인수를 취하지 않는다"는 의미). 당신은 아마도 유형의 대상을 가질 수 없습니다 void
. 항상. 따라서 존재하지 않는 객체의 크기를 찾아야 할 필요성을 알기가 어렵습니다. GCC의 행동은 비표준이며 의도적 인 확장. 그러나 나는 그들이 선택했다고 생각합니다 sizeof(void) == 1
C ++ 표준은 모든 객체가 하나 이상의 바이트의 공간을 차지해야하기 때문입니다.
void*
"실제 데이터에 대한 포인터이지만 관련 유형 정보가 없음"을 의미합니다. 전적으로 가질 수 있습니다 void*
; 그리고 당신은 그들에게 많이 달릴 것입니다. 그러나 유형 정보가 무시되므로 포인터를 많이 조작 할 수 없습니다. 이것은 당신이 무엇을 가지고 있는지 모른다면 당신이 그것으로 무엇을 할 수 있는지 모르기 때문에 디자인에 의한 것입니다.
하지만 메모리를 바이트 모음으로 취급하려면 char*
것을 수행. ㅏ char
어디에서나 하나의 바이트입니다. 바이트 문자열은 a입니다 char*
. 이 이상한 것을 발견하면 사용하십시오 byte*
(당신이 정의하는 곳 byte
같은 것입니다 unsigned char
).
첫 번째 줄의 오류를 적어도 볼 수 있습니다. 적어도 크기 (void)가 있고 sizeof (void*) 여야합니다.
순수하게 원시 데이터를 가리키고 해당 포인터를 바이트 수로 증가시키기 위해서는 항상 사용합니다. char *
. 그런 다음 관련 데이터 구조 포인터에 대한 포인터를 구체적인 것으로 취급해야합니다. 증분 a void *
컴파일러 중 휴대용이 아닙니다.
void *는 잘 인식되고 원시 메모리에 대한 유형이없는 포인터로 사용됩니다.
옳은. 유형이없는 것은 크기가없는 것을 의미합니다.