의 크기

sizeof

sizeof는 프로그래밍 언어 C와 C++단항 연산자다.이것은 표현식 또는 데이터 유형의 저장 크기를 생성하며, 문자 크기 단위 수로 측정된다.따라서 (char)의 구성 크기1이 될 것으로 보장된다.유형 문자 유형의 실제 비트 수는 전처리기 매크로에 의해 지정됨 표준에 정의된 CHAR_BIT에는 filelimits.h포함된다.대부분의 현대 컴퓨팅 플랫폼에서 이것은 8비트다.sizeof의 결과는 일반적으로 size_t로 표시되는 부호 없는 정수 유형을 가진다.null

연산자는 하나의 피연산자를 가지고 있는데, 이 피연산자는 표현식이나 데이터 유형의 캐스트 중 하나이며, 괄호 안에 둘러싸인 데이터 유형이다.데이터 유형은 정수 및 부동 소수점 유형과 같은 원시 유형일 뿐만 아니라 포인터 유형, 복합 데이터 유형(유니온, 구조체 및 C++ 클래스)일 수 있다.null

목적

많은 프로그램은 특정 데이터 유형의 저장 크기를 알아야 한다.C 또는 C++의 어떤 주어진 구현의 경우 특정 데이터 유형의 크기가 일정하지만, C와 C++의 원시 유형의 크기는 구현 플랫폼마다 다르게 정의될 수 있다.예를 들어, 어레이 공간의 런타임 할당은 연산자 크기가 int형식의 캐스트에 적용되는 다음과 같은 코드를 사용할 수 있다.

int *size = malloc(10 * size of (int));

이 예에서 함수 malloc는 메모리를 할당하고 포인터를 메모리 블록에 반환한다.할당된 블록의 크기는 10개의 정수를 위한 공간을 제공하는 int형식의 단일 객체에 대한 바이트 수와 같다.null

일반적으로 데이터 유형의 크기를 가정하는 것은 안전하지 않다.예를 들어, 32비트 시스템에 C와 C++를 구현한 대부분의 경우 형식 int를 4옥텟으로 정의하지만, 코드가 다른 시스템에 포팅되어 코드를 파괴할 때 이 크기가 변경될 수 있다.이에 대한 예외는 데이터 유형 문자인데, 표준 준수 C 구현에서는 항상 크기가 1이다.또한 패딩으로 인해 구조체유니언과 같은 복합 데이터 유형의 크기를 예측하기 어려운 경우가 많다.크기를 사용하면 이름 없는 숫자 상수(마법 숫자)를 피할 수 있기 때문에 가독성이 향상된다.null

동일한 배열 공간을 할당하기 위한 동등한 구문은 저장 주소에 대한 참조되지 않은 포인터 형식을 사용하므로, 이번에는 연산자를 포인터 변수에 적용:

int *nt = malloc(10 * * size of *size);

사용하다

연산자 크기는 코드를 컴파일할 때 피연산자의 필요한 메모리 저장 공간을 생성한다.피연산자는 키워드 크기에 따라 작성되며, 예를 들어 변수, 표현식 또는 유형 캐스트와 같은 저장소 공간의 기호일 수 있다.후자는 괄호 안에 동봉된 형식 이름이다.연산자의 결과는 피연산자의 크기(바이트) 또는 메모리 저장 요구 사항의 크기.표현식의 경우, 표현식의 평가에서 비롯되는 유형의 표현 크기로 평가하며, 이는 수행되지 않는다.null

예를 들어 (char)의 크기는 1로[1] 정의되고 정수 유형이 4바이트라고 가정하면 다음과 같은 코드 조각이 인쇄된다.

char c; printf("%zu,%zu\n", c 크기, size of (int);

stddef.h와 같은 특정 표준 헤더 파일은 size_t를 정의하여 식 크기 결과의 서명되지 않은 정수 유형을 나타낸다.인쇄물 너비 지정자 z는 해당 형식을 포맷하기 위한 것이다.null

sizeof데이터 유형이 없는 전처리기 구문이 아니라 프로그래밍 언어의 요소이기 때문에 #if와 같은 C 전처리기 식에서 사용할 수 없다.null

C++의 다음 예는 가변 템플릿과 함께 의 연산자 크기를 사용한다.null

템플릿 <표준 이름...Args> std:size_t GetSize (Args&... args) { /* 파라미터 팩 크기 가져오기*/ std::size_t Count= size of...(아그), 반환 개수, }

sizeof는 변수 팩에서 C++11 이상의 가변 템플릿과 함께 사용할 수 있다.null

애플리케이션에서 어레이로

sizeof를 배열 이름에 적용하면 전체 배열을 저장하는 데 필요한 바이트 수가 된다.이는 배열의 이름이 배열의 첫 번째 요소에 대한 포인터로 변환되는 규칙의 몇 안 되는 예외 중 하나이며, 연산자의 크기를 평가할 때 컴파일 시간에 실제 배열 크기가 고정되고 알려지기 때문에 가능하다.다음 프로그램은 sizeof를 사용하여 선언된 배열의 크기를 결정하여 문자를 복사할 때 버퍼 오버플로를 방지한다.

#include <stdio>.h> 주(int argc, char **argv){문자 버퍼[10]; /* 10자 배열 */ /* 최대 9자를 argv[1]에서 버퍼로 복사한다.* 버퍼 null을 제거하십시오.*/snprintf(snprintf, 버퍼 크기, "%s", argv[1]; 반환 0;}

여기서 버퍼의 크기10 * buffer의 크기[0]에 해당하며, 이는 유형 char의 크기가 1로 정의되기 때문에 10으로 평가된다.

C99는 유연한 어레이 멤버에 대한 지원을 구조물에 추가한다.이 형태의 배열 선언은 구조물의 마지막 요소로서만 허용되며, 컴파일러에 길이가 지정되지 않는다는 점에서 일반 배열과 다르다.따라서 a라는 이름의 유연한 배열 멤버를 포함하는 s라는 이름의 구조물의 경우, s의 크기 (s, a)의 오프셋과 동일하다.

#include <stdio>.h> 구조체 플렉서레이 {char val;int 어레이[]; /* 유연한 어레이 멤버; 구조체의 마지막 요소여야 함 */}; 주(int argc, char **argv){printf("sizeof (multiple flexarray) == %zu\n", size of (multiple flexarray);반환 0;}

이 경우 운영자 크기는 패딩을 포함하여 구조물의 크기를 반환하지만 어레이에 허용된 저장소는 없다.대부분의 플랫폼은 다음과 같은 출력을 생성한다.

sizeof (struct flexarray) == 4

C99는 또한 이 기능이 C 표준의 이후 버전에서 선택적 구현으로 간주되지만 런타임에 지정된 길이를 가진 가변 길이 배열도 허용한다.[2]이러한 경우, 운영자의 크기는 어레이가 점유한 스토리지를 결정하기 위해 런타임에 부분적으로 평가된다.null

#1901 <stddef>.h> size_t flexsize(int n) { char b[n + 3]; /* 가변 길이 어레이 */ b의 반환 크기; /* */ } main(void) { size_t size = flexsize(10); /* flex size retset 13 */ ret return 0; }

sizeof는 전체 배열의 크기를 단일 요소의 크기로 나누어 배열의 요소 수를 결정하는 데 사용할 수 있다.

}

불완전한 유형

size of는 "size" 정의된 형식에만 적용할 수 있다.배열과 함께, 이것은 배열의 치수가 그 선언에 존재해야 하며, 원소의 유형은 완전히 정의되어야 함을 의미한다.구조체 조합의 경우, 이는 완전히 정의된 유형의 구성원 목록이 있어야 함을 의미한다.예를 들어 다음 두 개의 원본 파일을 고려하십시오.

/* file1.c */ int ar [10], 구조 x {int 1; int 2;}; /* 더 많은 코드 */ /* file2.c */ extern int ar []; 구조체 x; /* 더 많은 코드 */

두 파일 모두 완벽하게 합법적인 C이며, file1.c의 코드는 arrstructure xsizeof를 적용할 수 있다.그러나 file2.c의 정의가 완전하지 않기 때문에 file2.c의 코드가 이렇게 하는 것은 불법이다.arr의 경우, 코드는 배열의 치수를 명시하지 않는다. 이 정보가 없으면 컴파일러는 배열 안에 몇 개의 요소가 있는지 알 방법이 없고, 배열의 전체 크기를 계산할 수 없다.마찬가지로 컴파일러는 자신이 어떤 구성원으로 구성되어 있는지 모르기 때문에 구조체 x의 크기를 계산할 수 없으며, 따라서 구조체 구성원(및 패딩)의 크기 합계를 계산할 수 없다.프로그래머가 파일2.c의 선언에서 배열의 크기를 제공하거나, 구성원 목록을 제공하여 구조체 x의 정의를 완료한 경우, 이것은 소스 파일에서 arr 또는 구조체 x에 size of를 적용할 수 있다.null

오브젝트 구성원

C++11은 이를 달성하기 위해 대상을 인스턴스화할 필요 없이 특정 클래스 멤버에게 매개변수 크기를 적용할 수 있는 가능성을 도입했다.[3]다음은 수익률과 대부분의 플랫폼의 예다.null

#buit <iostream> 구조 foo { int a; int b; }; int main() { std:::cout << foo::a< \n> size of << size of (foo)><\n; }

가변 템플릿 팩

C++11은 가변 템플릿을 도입했다. 키워드 크기 줄임표가 붙는 것은 매개변수 팩의 요소 수를 반환한다.null

템플릿 <표준 이름...Args> void print_size (Args...args) { std::cout << size of...(args) << "\n"; } in main ({ print_size (); // 출력 0 print_size ("답변", 42, true); // 출력 3 }

실행

고정 길이 데이터 유형 또는 변수에 적용할 경우 프로그램 컴파일 중에 연산자 size of가 포함된 식을 평가하여 일정한 결과 값으로 대체한다.C99 표준은 VLA(Variable-Length Arrays)를 도입했는데, 프로그램 실행 중 이러한 표현에 대한 평가가 필요했다.많은 경우에, 구현 세부사항은 컴파일러가 준수해야 하는 데이터 유형에 대한 형식, 패딩 및 정렬을 명시하여 플랫폼용 애플리케이션 이진 인터페이스(ABI) 문서에 문서화될 수 있다.null

구조 패딩

어떤 객체 유형의 크기를 계산할 때, 컴파일러는 효율성 또는 구조적 제약을 충족하기 위해 필요한 데이터 구조 정렬을 고려해야 한다.많은 컴퓨터 아키텍처들은 단어 크기의 배수가 아닌 어떤 바이트 주소에서 시작하는 다중 바이트 접근을 지원하지 않으며, 심지어 구조가 그것을 허용하더라도, 프로세서는 대개 메모리에서 여러 단어를 늘어놓는 물체를 가져올 수 있는 것보다 더 빨리 단어 정렬된 물체를 가져올 수 있다.[4]따라서 컴파일러는 일반적으로 데이터 구조를 최소한 단어 경계와 일치시키고, 또한 개별 구성원을 각각의 경계와 일치시킨다.다음의 예에서 구조 학생은 단어 경계선에 정렬될 가능성이 높으며, 이것은 또한 회원 등급이 시작되는 곳이며, 회원 연령은 다음 단어 주소에서 시작될 가능성이 높다.컴파일러는 정렬 요건을 충족하기 위해 필요한 경우 멤버 사이에 패딩 바이트를 삽입하여 후자를 달성한다.구조물이 배열의 요소로 사용되는 경우에 적절한 정렬을 보장하기 위해 구조물의 끝에 패딩이 있을 수도 있다.null

따라서 C에서 구조물의 총 크기는 개별 구성원의 크기 합계보다 클 수 있다.예를 들어, 많은 시스템에서 다음 코드가 인쇄된다.

구조체 학생 { char 등급; /* char는 1바이트 길이 */ int 나이, /* int는 4바이트 길이 */ }; printf("%zu"), size of (size);

참고 항목

참조

  1. ^ "C99 standard (ISO/IEC9899)" (PDF). ISO/IEC. 7 September 2007. 6.5.3.4.3, p. 80. Retrieved 31 October 2010.
  2. ^ "WG14/N1124 Committee Draft ISO/IEC 9899" (PDF). 6 May 2005. 6 May 2005. 6.5.3.4 The sizeof operator.
  3. ^ "N2253 Extending sizeof to apply to non-static data members without an object (Revision 1)".
  4. ^ Rentzsch, Jonathan (8 February 2005). "Data alignment: Straighten up and fly right". www.ibm.com. Retrieved 29 September 2014.