예를 들어
sizeof(char*)
로는 않습니다 4. 반환 int*
, long long*
내가 해봤 모든 것을. 이것에 대한 예외가 있습니까?
예를 들어
sizeof(char*)
로는 않습니다 4. 반환 int*
, long long*
내가 해봤 모든 것을. 이것에 대한 예외가 있습니까?
답변:
당신이 얻는 보증은입니다 sizeof(char) == 1
. 보증 없음을 포함하여 다른 보증은 없습니다 sizeof(int *) == sizeof(double *)
.
실제로, 포인터는 16 비트 시스템에서 크기 2 (하나를 찾을 수있는 경우), 32 비트 시스템에서 4 개, 64 비트 시스템에서 8입니다. 크기.
일반 x86 32 비트 플랫폼에서도 다양한 포인터 크기를 얻을 수 있습니다. 예를 들어 다음을 시도해보십시오.
struct A {};
struct B : virtual public A {};
struct C {};
struct D : public A, public C {};
int main()
{
cout << "A:" << sizeof(void (A::*)()) << endl;
cout << "B:" << sizeof(void (B::*)()) << endl;
cout << "D:" << sizeof(void (D::*)()) << endl;
}
Visual C ++ 2008에서 포인터 대 멤버 함수의 크기에 대해 4, 12 및 8을 얻습니다.
Raymond Chen은 이에 대해 이야기 했습니다 .
이미 게시 된 목록에 대한 또 다른 예외입니다. 32 비트 플랫폼에서 포인터는 4 바이트가 아닌 6 바이트를 사용할 수 있습니다 .
#include <stdio.h>
#include <stdlib.h>
int main() {
char far* ptr; // note that this is a far pointer
printf( "%d\n", sizeof( ptr));
return EXIT_SUCCESS;
}
Open Watcom으로이 프로그램을 컴파일하고 실행하면 지원되는 멀리 포인터가 32 비트 오프셋 및 16 비트 세그먼트 값으로 구성되므로 6을 얻게됩니다.
64 비트 컴퓨터 용으로 컴파일하는 경우 8 일 수 있습니다.
sizeof(char*)==1
? 확실합니까? 당신은 의미하지 size(char)==1
않습니까?
기술적으로 말하면 C 표준은 sizeof (char) == 1 만 보장하며 나머지는 구현에 달려 있습니다. 그러나 최신 x86 아키텍처 (예 : Intel / AMD 칩)에서는 상당히 예측 가능합니다.
아마도 16 비트, 32 비트, 64 비트 등의 프로세서가 있다고 들었을 것입니다. 이는 일반적으로 프로세서가 정수에 N 비트를 사용함을 의미합니다. 포인터는 메모리 주소를 저장하고 메모리 주소는 정수이므로 포인터에 사용될 비트 수를 효과적으로 알려줍니다. sizeof는 일반적으로 바이트 단위로 측정되므로 32 비트 프로세서 용으로 컴파일 된 코드는 포인터 크기를 4 (32 비트 / 8 비트 당 8 비트)로보고하고 64 비트 프로세서 용 코드는 포인터 크기를 8로보고합니다. (바이트 당 64 비트 / 8 비트). 32 비트 프로세서에 대한 4GB RAM의 한계는 여기서 시작합니다. 각 메모리 주소가 바이트에 해당하는 경우 더 많은 메모리를 처리하려면 32 비트보다 큰 정수가 필요합니다.
포인터의 크기는 기본적으로 포인터가 구현되는 시스템의 아키텍처에 따라 다릅니다. 예를 들어 32 비트의 포인터 크기는 64 비트 시스템에서 4 바이트 (32 비트) 및 8 바이트 (64 비트)입니다. 머신의 비트 타입은 메모리 주소에 지나지 않습니다. 32 비트 시스템은 2^32
주소 공간을 가질 수 있고 64 비트 시스템은 최대 2^64
주소 공간을 가질 수 있습니다 . 따라서 포인터 (메모리 위치를 가리키는 변수)는 2^32 for 32 bit and 2^64 for 64 bit
머신이 보유한 메모리 주소 ( ) 를 가리킬 수 있어야합니다 .
이러한 이유로 포인터 크기는 32 비트 시스템에서 4 바이트, 64 비트 시스템에서 8 바이트입니다.
16/32/64 비트 차이 외에도 이상한 일이 발생할 수 있습니다.
sizeof (int *)가 하나의 값이되는 기계가 있었을 것입니다. 아마도 4 일 것입니다. 그러나 sizeof (char *)는 더 큽니다. 바이트 대신 단어를 자연스럽게 처리하는 기계는 C / C ++ 표준을 올바르게 구현하기 위해 실제로 원하는 단어 부분을 지정하기 위해 문자 포인터를 "증가"해야합니다.
하드웨어 설계자들이 바이트 어 드레서 빌 러티의 가치를 알게되면서 이것은 매우 드문 일입니다.
void*
및 char*
소프트웨어에서 처리되고, 워드 내 오프셋 3 비트로 증대된다 - 그러나, 실제로는 64 비트 어드레스 공간이 없기 때문에, 상위의 64 비트의 3 비트를 저장 오프셋 워드. 그래서 char*
와 int*
같은 크기,하지만 서로 다른 내부 표현 - 그리고 포인터가 "정말"그냥 정수가 심하게 실패 할 것으로 가정합니다 코드를.
내가 기억하는 것에서 메모리 주소의 크기를 기반으로합니다. 따라서 32 비트 주소 체계가있는 시스템에서 sizeof는 4 바이트이므로 4를 반환합니다.
sizeof (unsigned int) == sizeof (signed int)
에서이 요구 사항은 3.9.1 / 3에 있습니다. "유형 정수 서명 표준 각각에 대해 대응하는 (그러나 다른) 표준 부호 정수의 형태가 존재한다 : unsigned char
, unsigned short int
, unsigned int
, unsigned long int
, 및 unsigned long long int
, 이들 각각은 같은 크기의 저장 용량을 차지하고 형 정수 서명 대응 같은 정렬 요건을 갖는다 "
Windows 32 비트 시스템의 Turbo C 컴파일러에서 포인터 및 int의 크기는 2 바이트입니다.
따라서 포인터의 크기는 컴파일러마다 다릅니다. 그러나 일반적으로 대부분의 컴파일러는 32 비트에서 4 바이트 포인터 변수를, 64 비트 시스템에서 8 바이트 포인터 변수를 지원하도록 구현됩니다.
따라서 포인터 크기는 모든 기계에서 동일하지 않습니다.
에서 Win64를 (Cygwin에서 GCC 5.4) ,의 예를 아래에 보자 :
먼저 다음 구조체를 테스트하십시오.
struct list_node{
int a;
list_node* prev;
list_node* next;
};
struct test_struc{
char a, b;
};
테스트 코드는 다음과 같습니다.
std::cout<<"sizeof(int): "<<sizeof(int)<<std::endl;
std::cout<<"sizeof(int*): "<<sizeof(int*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(double): "<<sizeof(double)<<std::endl;
std::cout<<"sizeof(double*): "<<sizeof(double*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(list_node): "<<sizeof(list_node)<<std::endl;
std::cout<<"sizeof(list_node*): "<<sizeof(list_node*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(test_struc): "<<sizeof(test_struc)<<std::endl;
std::cout<<"sizeof(test_struc*): "<<sizeof(test_struc*)<<std::endl;
출력은 다음과 같습니다.
sizeof(int): 4
sizeof(int*): 8
sizeof(double): 8
sizeof(double*): 8
sizeof(list_node): 24
sizeof(list_node*): 8
sizeof(test_struc): 2
sizeof(test_struc*): 8
64 비트에서 sizeof(pointer)
is 8
입니다.
포인터는 주소의 컨테이너 일뿐입니다. 32 비트 시스템에서 주소 범위는 32 비트이므로 포인터는 항상 4 바이트입니다. 64 비트 시스템에서 주소 범위가 64 비트 인 경우 포인터는 8 바이트입니다.
완전성과 역사적 관심을 위해 64 비트 세계에서 LLP64 및 LP64라는 길고 긴 long 유형의 크기에 대해 주로 Unix 유형 시스템과 Windows간에 서로 다른 플랫폼 규칙이있었습니다. ILP64라는 오래된 표준도 int = 64 비트 폭으로 만들었습니다.
Microsoft는 LLP64를 longlong = 64 비트 너비로 유지했지만 더 쉽게 이식 할 수 있도록 32로 유지했습니다.
Type ILP64 LP64 LLP64
char 8 8 8
short 16 16 16
int 64 32 32
long 64 64 32
long long 64 64 64
pointer 64 64 64