Program Tip

다른 유형에 대한 포인터의 크기가 다른 플랫폼이 있습니까?

programtip 2020. 12. 15. 19:45
반응형

다른 유형에 대한 포인터의 크기가 다른 플랫폼이 있습니까?


C 표준은 다른 유형에 대한 포인터가 다른 크기를 갖도록 sizeof(char*) != sizeof(int*)허용합니다 ( 예 : 허용됨). 그러나 포인터가 a void*로 변환 된 다음 다시 원래 유형으로 변환되면 원래 값과 동일한 것으로 비교해야합니다. 따라서 논리적으로 sizeof(void*) >= sizeof(T*)모든 유형 T에 대해 맞습니까?

오늘날 사용되는 가장 일반적인 플랫폼 (x86, PPC, ARM 및 64 비트 변형 등)에서 모든 포인터의 크기는 지정 대상 유형에 관계없이 기본 레지스터 크기 (4 또는 8 바이트)와 같습니다. 다른 유형에 대한 포인터의 크기가 다를 수있는 난해하거나 임베디드 플랫폼이 있습니까? 함수 포인터가 비정상적인 크기를 갖는 플랫폼이 있는지도 알고 싶지만 데이터 포인터 에 대해 구체적으로 묻고 있습니다 .

나는 C ++의 포인터-멤버와 포인터-멤버-함수에 대해 확실히 묻지 않는다 . 그것들은 일반적인 플랫폼에서 비정상적인 크기를 취하고, 포인터에 대한 클래스 (비다 형성, 단일 상속, 다중 상속, 가상 상속 또는 불완전 유형)의 속성에 따라 하나의 플랫폼 내에서도 달라질 수 있습니다.


C FAQ의 답변 :

Prime 50 시리즈는 최소한 PL / I에 대해 널 포인터에 대해 세그먼트 07777, 오프셋 0을 사용했습니다. 이후 모델은 C의 널 포인터에 대해 세그먼트 0, 오프셋 0을 사용했으며, TCNP (Test C Null Pointer)와 같은 새로운 명령이 필요했습니다. 이전의 단어 주소가 지정된 Prime 시스템은 단어 포인터 (int *)보다 더 큰 바이트 포인터 (char *)를 요구하는 것으로 악명이 높습니다.

Data General의 Eclipse MV 시리즈에는 아키텍처 적으로 지원되는 세 가지 포인터 형식 (워드, 바이트 및 비트 포인터)이 있으며,이 중 두 가지는 C 컴파일러에서 사용됩니다. char * 및 void *에 대한 바이트 포인터와 그 밖의 모든 것에 대한 워드 포인터입니다. 16 비트 Nova 라인에서 32 비트 MV 라인이 진화하는 동안 역사적인 이유로 워드 포인터와 바이트 포인터는 워드의 다른 위치에 오프셋, 간접 및 링 보호 비트를 가졌습니다. 일치하지 않는 포인터 형식을 함수에 전달하면 보호 오류가 발생했습니다. 결국 MV C 컴파일러는 포인터 유형 불일치 오류가있는 코드를 처리하기 위해 많은 호환성 옵션을 추가했습니다.

일부 Honeywell-Bull 메인 프레임은 (내부) 널 포인터에 비트 패턴 06000을 사용합니다.

CDC Cyber ​​180 시리즈에는 링, 세그먼트 및 오프셋으로 구성된 48 비트 포인터가 있습니다. 대부분의 사용자 (링 11에서)는 0xB00000000000의 널 포인터를 가지고 있습니다. 오래된 CDC 1s 보완 시스템에서는 유효하지 않은 주소를 포함하여 모든 종류의 데이터에 대한 특수 플래그로 all-one-bits 단어를 사용하는 것이 일반적이었습니다.

이전 HP 3000 시리즈는 바이트 주소에 대해 워드 주소와 다른 주소 지정 체계를 사용합니다. 위의 여러 기계와 마찬가지로 다른 포인터보다 char * 및 void * 포인터에 대해 다른 표현을 사용합니다.

태그가 지정된 아키텍처 인 Symbolics Lisp Machine에는 기존의 숫자 포인터도 없습니다. 쌍 (기본적으로 존재하지 않는 핸들)을 C 널 포인터로 사용합니다.

사용중인``메모리 모델 ''에 따라 8086 제품군 프로세서 (PC 호환)는 16 비트 데이터 포인터와 32 비트 함수 포인터를 사용하거나 그 반대의 경우도 가능합니다.

일부 64 비트 Cray 머신은 단어의 하위 48 비트에서 int *를 나타냅니다. char *는 상위 16 비트 중 일부를 추가로 사용하여 단어 내의 바이트 주소를 나타냅니다.

추가 링크 : 이러한 컴퓨터 중 일부에 대한 자세한 내용이 포함 된 Chris Torek메시지 .


원하는 것은 아니지만 16 비트 DOS / Windows 시절에는 포인터와 원거리 포인터를 구분했으며 후자는 32 비트였습니다.

구문이 잘못되었을 수 있습니다.

int *pInt = malloc(sizeof(int));
int far *fpInt = _fmalloc(sizeof(int));

printf("pInt: %d, fpInt: %d\n", sizeof(pInt), sizeof(fpInt));

산출:

핀 : 2, fpInt 4


따라서 논리적으로 sizeof(void*) >= sizeof(T*)모든 유형 T에 대해 맞습니까?

sizeof는 스토리지 표현에 관한 것이고 모든 비트 패턴이 유효한 값일 필요는 없기 때문에 반드시 따르는 것은 아닙니다. 어디서 당신이 준수 구현을 쓸 수있는 생각 sizeof(int*) == 8, sizeof(void*) == 4하지만있는 int *에 대한 더 이상 32 ^ 2 이상의 수있는 값이 있습니다. 왜 원하는지 모르겠습니다.


DOS, 8088s 및 세그먼트 메모리의 황금기에는 모든 코드가 64k (한 세그먼트)에 맞지만 데이터가 여러 세그먼트에 걸쳐있을 수있는 "메모리 모델"을 지정하는 것이 일반적이었습니다. 이것은 함수 포인터가 2 바이트, 데이터 포인터, 4 바이트라는 것을 의미합니다. 누군가가 여전히 그런 종류의 기계를 위해 프로그래밍하고 있는지 확실하지 않지만 일부는 여전히 임베디드 사용에서 살아남을 수 있습니다.


함수 포인터와 다른 모든 포인터에 대해 크기가 다른 하버드 아키텍처 머신을 쉽게 상상할 수 있습니다. 예를 모른다 ...


근거리 및 원거리 포인터는 동일한 페이지 (근접 포인터) 또는 다른 페이지 (페이지 정보를 포함하기 때문에 더 큰 원거리 포인터)의 데이터를 가리킬 수 있도록 페이징 된 플래시 또는 RAM이있는 일부 임베디드 마이크로 컨트롤러에서 여전히 사용됩니다.

예를 들어, Freescale의 HCS12 마이크로 컨트롤러는 16 비트 Von Neumann 아키텍처를 사용합니다. 이는 주소가 16 비트를 초과 할 수 없음을 의미합니다. 이로 인해 사용 가능한 코드 공간의 양이 제한되므로 8 비트 페이지 레지스터가 있습니다.

따라서 동일한 코드 페이지의 데이터를 가리 키려면 16 비트 주소 만 지정하면됩니다. 이것은 가까운 포인터입니다.

다른 코드 페이지의 데이터를 가리 키려면 해당 페이지 내에 8 비트 페이지 번호와 16 비트 주소를 모두 포함해야하므로 24 비트 원거리 포인터가 생성됩니다.


예를 들어 데이터에 대한 포인터의 크기가 함수에 대한 포인터와 다를 수 있습니다. 이것은 임베디드 시스템 용 마이크로 프로세서에서 흔히 발생합니다. 언급 한 dmckee와 같은 하버드 아키텍처 머신은이를 쉽게 수행 할 수 있습니다.

gcc 백엔드를 개발하는 데 어려움을 겪는 것으로 나타났습니다! :)

편집 : 제가 이야기하고있는 특정 컴퓨터에 대한 세부 사항은 설명 할 수 없지만 Harvard 컴퓨터가이 작업을 쉽게 수행 할 수있는 이유를 추가하겠습니다. Harvard 아키텍처는 명령어와 데이터에 대한 저장과 경로가 다르므로 명령어 용 버스가 데이터 용 버스보다 '더 크다'면 데이터에 대한 포인터보다 크기가 더 큰 함수 포인터를 갖게됩니다!

참조 URL : https://stackoverflow.com/questions/916051/are-there-any-platforms-where-pointers-to-different-types-have-different-sizes

반응형