부호없는 int와 size_t


492

나는 현대 C 통지 및 C ++ 코드를 사용하는 것 size_t대신에 int/ unsigned int거의 모든 곳에서 - STL과에 C 문자열 함수에 대한 매개 변수에서. 나는 이것의 이유와 그것이 가져다주는 이점에 대해 궁금합니다.

답변:


388

size_t유형의 결과 인 부호없는 정수 타입 sizeof연산자 (그리고 offsetof이 시스템이 처리 할 수있는 가장 큰 객체 (예를 들면, 8GB의의 정적 배열)의 크기를 포함하도록 충분히 큰 보장되도록, 연산자).

size_t유형은보다보다 큰 같거나 작을 수있다 unsigned int, 당신의 컴파일러 최적화를 위해 그것에 대해 인식 할 수 있습니다.

인터넷에서 pdf 형식으로 제공되는 C99 표준 섹션 7.17, pdf 초안으로 제공되는 C11 표준 섹션 7.19 에서보다 정확한 정보를 찾을 수 있습니다 .


50
아니. x86-16을 큰 (거대하지 않은) 메모리 모델로 생각해보십시오. 포인터는 먼 (32 비트)이지만 개별 객체는 64k로 제한됩니다 (따라서 size_t는 16 비트 일 수 있습니다).
dan04

8
"가장 큰 객체의 크기"는 나쁜 표현이 아니지만 절대적으로 정확합니다. 객체의 6은 주소 공간보다 훨씬 더 제한 될 수 있습니다.
gnasher729

3
"컴파일러가 가정 할 수 있습니다": 컴파일러 size_t 표현할 수 있는 정확한 범위의 값을 알고 있기를 바랍니다 . 그렇지 않은 경우 누가합니까?
Marc van Leeuwen 2016 년

4
@ MARC : 컴파일러가 그 지식으로 무언가 를 할 수 있다는 것이 요점이라고 생각합니다 .

8
나는 점점 인기가있는이 유형이 헤더 파일을 포함하지 않아도되기를 바랍니다.
user2023370 10


73

요컨대, size_t부정적이지 않으며, 대상 플랫폼에서 가능한 가장 큰 객체의 크기를 나타내기에 충분히 크지 않지만 너무 크지 않은 부호없는 정수 유형으로 typedef이기 때문에 성능을 최대화합니다.

크기는 음수이면 안되며 실제로 size_t부호없는 유형입니다. 또한 size_t부호가 없으므로 부호없는 정수의 다른 모든 비트와 같이 부호 비트를 사용하여 크기를 나타낼 수 있기 때문에 해당 부호있는 유형보다 약 두 배 큰 숫자를 저장할 수 있습니다. 비트를 하나 더 얻으면, 표현할 수있는 숫자의 범위에 약 2 배를 곱합니다.

그래서 당신은 묻습니다. 왜 그냥 unsigned int? 큰 숫자를 보유하지 못할 수 있습니다. unsigned int32 비트 인 구현에서 나타낼 수있는 가장 큰 숫자는입니다 4294967295. IP16L32와 같은 일부 프로세서는 4294967295바이트 보다 큰 객체를 복사 할 수 있습니다 .

그래서, 당신은 묻지 unsigned long int않습니까? 일부 플랫폼에서 성능이 저하됩니다. 표준 C는 long32 비트 이상을 차지 해야합니다 . IP16L32 플랫폼은 각 32 비트 길이를 한 쌍의 16 비트 워드로 구현합니다. 이 플랫폼의 거의 모든 32 비트 연산자는 두 개의 16 비트 청크에서 32 비트와 함께 작동하기 때문에 두 개 이상의 명령이 필요합니다. 예를 들어, 32 비트 길이를 이동하려면 일반적으로 각 16 비트 청크를 이동하는 두 개의 기계 명령어가 필요합니다.

를 사용 size_t하면이 성능이 저하됩니다. 이 환상적인 기사 에 따르면 , "유형 size_t은 부호없는 정수 유형의 별칭 인 typedef입니다. 일반적으로 unsigned int또는 unsigned long가능할 수도 unsigned long long있습니다. 각 표준 C 구현은 충분히 크지 만 필요한 것보다 크지 않은 부호없는 정수를 선택해야합니다. 대상 플랫폼에서 가능한 가장 큰 물체의 크기를 나타냅니다. "


1
너무 오래 후 이것에 대해 언급 해 죄송하지만 서명되지 않은 int가 보유 할 수있는 가장 큰 숫자를 확인해야했습니다. 어쩌면 귀하의 용어를 오해하고 있지만 서명되지 않은 int가 보유 할 수있는 가장 큰 숫자는 4294967295, 65356입니다 부호없는 short의 최대 값
Mitch

부호없는 int가 32 비트를 차지하는 경우 예를 들어 보유 할 수있는 가장 큰 숫자는 2 ^ 32-1이며 4294967295 (0xffffffff)입니다. 다른 질문이 있습니까?
Rose Perrone

3
@Mitch : 캔으로 표현할 수 있고 unsigned int시스템마다 다른 최대 값 . 할 필요가있어 적어도 65536 하지만 일반적입니다 4294967295및 수 18446744073709551615일부 시스템 (2 ** 64-1).
Keith Thompson

1
16 비트 부호없는 int가 포함 할 수있는 가장 큰 값은 65536이 아니라 65535입니다. 65536과의 작지만 중요한 차이는 16 비트 부호없는 int의 0과 같습니다.
Sie Raybould

1
@ gnasher729 : C ++ 표준에 대해 확신하십니까? 얼마 동안 검색 한 결과 정수 범위 (제외 unsigned char)에 대한 모든 절대 보장이 단순히 제거되었다는 인상을 받았습니다 . 표준은 문자열 '65535'또는 '65536'을 어디에도 포함하지 않는 것으로 보이며 '+32767'은 (1.9 : 9) 참고로 표현할 수있는 가장 큰 정수로 나타납니다 int. INT_MAX그것보다 작을 수 없다고 보장 할 수는 없습니다!
Marc van Leeuwen

51

size_t 타입은 sizeof 연산자에 의해 반환되는 타입입니다. 호스트 시스템에서 지원되는 모든 메모리 범위의 크기를 바이트 단위로 표현할 수있는 부호없는 정수입니다. ptrdiff_t가 부호있는 정수 값이므로 sizeof (ptrdiff_t)와 sizeof (size_t)가 동일하다는 것은 (일반적으로) ptrdiff_t와 관련이 있습니다.

C 코드를 작성할 때는 메모리 범위를 다룰 때마다 항상 size_t 를 사용해야 합니다.

반면에 int 유형은 기본적으로 호스트 시스템이 정수 산술을 가장 효율적으로 수행하는 데 사용할 수있는 (부호있는) 정수 값의 크기로 정의됩니다. 예를 들어 많은 구형 PC 유형 컴퓨터에서 sizeof (size_t) 값은 4 (바이트)이지만 sizeof (int)는 2 (바이트)입니다. CPU는 최대 4GiB의 (논리적) 메모리 공간을 처리 할 수 ​​있지만 16 비트 산술은 32 비트 산술보다 빠릅니다.

실제 정밀도는 컴파일러 옵션과 머신 아키텍처에 크게 좌우되므로 효율성에 관심이있는 경우에만 int 유형을 사용하십시오. 특히 C 표준은 다음과 같은 불변량을 지정합니다. sizeof (char) <= sizeof (short) <= sizeof (int) <= sizeof (long) 각각에 대해 프로그래머가 사용할 수있는 정밀도의 실제 표현에는 다른 제한이 없습니다. 이러한 기본 유형.

참고 : 이것은 Java와 동일하지 않습니다 (실제로 'char', 'byte', 'short', 'int'및 'long'유형 각각의 비트 정밀도를 지정 함).


int의 사실상 정의는 16 대의 컴퓨터에서는 16 비트이고 더 큰 것은 32 비트입니다. int의 너비가 32 비트라고 가정하여이를 변경하기 위해 너무 많은 코드가 작성되었으며 결과적으로 사람들이 특정한 것을 원할 경우 항상 size_t 또는 {, u} int {8,16,32,64} _t를 사용해야합니다. -예방책으로 사람들은 정수형 정수 대신 항상 이것을 사용해야합니다.
Clearer

3
"호스트 컴퓨터에서 지원되는 모든 메모리 범위의 크기를 바이트 단위로 표현할 수있는 부호없는 정수입니다." -> No. size_t는 단일 객체의 크기 (예 : 숫자, 배열, 구조)를 나타낼 수 있습니다. 전체 메모리 범위는 다음을 초과 할 수 있습니다.size_t
chux-Reinstate Monica

"C 코드를 작성할 때 메모리 범위를 다룰 때마다 항상 size_t를 사용해야합니다." 즉, 모든 배열에 대한 모든 인덱스가 있어야 size_t함을 의미합니다. 대부분의 경우 주소 공간 + 이식성의 카디널리티가 중요한 배열은 다루지 않습니다. 이 경우에 당신은 걸릴 것 size_t입니다. 다른 모든 경우에는 (부호있는) 정수에서 인덱스를 가져옵니다. 서명되지 않은 언더 플로 동작에서 발생하는 혼동 (경고없이 제공됨)이 다른 경우에 발생할 수있는 이식성 문제보다 더 일반적이고 더 나쁩니다.
johannes_lalala

23

size_t 유형은 가능한 객체의 크기를 저장하기에 충분히 커야합니다. 부호없는 int는 해당 조건을 만족시킬 필요가 없습니다.

예를 들어 64 비트 시스템에서 int 및 unsigned int는 32 비트 너비 일 수 있지만 size_t는 4G보다 큰 숫자를 저장하기에 충분히 커야합니다.


38
"객체"는 표준에서 사용되는 언어입니다.
R .. GitHub 중지 지원 얼음

2
size_t컴파일러가 sizeof (X)가 4G보다 큰 값을 생성하도록 X 유형을 허용 할 수 있다면 그 크기 만 커야 한다고 생각 합니다. 대부분의 컴파일러는 예를 들어 거부 할 것이라고 typedef unsigned char foo[1000000000000LL][1000000000000LL]도하고, foo[65536][65536];그것을 문서화 구현 정의 된 제한을 초과하는 경우 합법적으로 거부 할 수있다.
supercat

1
@ MatJoiner : 문구는 괜찮습니다. "개체"는 전혀 모호하지 않고 "저장 영역"을 의미하도록 정의됩니다.
궤도에서 가벼움 레이스

4

glibc 매뉴얼 0.02에서 발췌 한 내용은 다음 주제를 연구 할 때도 관련이있을 수 있습니다.

2.4 이전의 size_t 유형 및 GCC 버전에는 잠재적 인 문제가 있습니다. ANSI C에서는 size_t가 항상 부호없는 유형이어야합니다. 기존 시스템의 헤더 파일과의 호환성을 위해 GCC는 stddef.h' to be whatever type the system'ssys / types 에서 size_t를 정의합니다 .h '는이를 정의합니다. `sys / types.h '에서 size_t를 정의하는 대부분의 유닉스 시스템은이를 서명 된 유형으로 정의합니다. 라이브러리의 일부 코드는 size_t가 서명되지 않은 유형에 따라 다르며 서명 된 경우 올바르게 작동하지 않습니다.

size_t가 부호없는 것으로 예상되는 GNU C 라이브러리 코드가 정확합니다. 서명 된 유형으로 size_t의 정의가 올바르지 않습니다. 버전 2.4에서는 GCC가 size_t를 부호없는 유형으로 정의하고 fixincludes' script will massage the system'ssys / types.h '와 충돌하지 않도록 항상 계획합니다 .

그 동안 GNU C 라이브러리를 컴파일 할 때 GCC에 size_t에 부호없는 유형을 사용하도록 명시 적으로 지정하여이 문제를 해결합니다. `configure '는 필요한 경우 GCC가 size_t를 재정의하기 위해 사용하는 유형을 자동으로 감지합니다.


2

내 컴파일러가 32 비트로 설정된 size_t경우에 대한 typedef 이외의 아무것도 아닙니다 unsigned int. 내 컴파일러가 64 비트로 설정된 size_t경우에 대한 typedef 이외의 아무것도 아닙니다 unsigned long long.


1
unsigned long일부 OS에서 두 경우 모두에 대해 정의 할 수 있습니다 .
StaceyGirl

-4

size_t는 포인터의 크기입니다.

따라서 32 비트 또는 공통 ILP32 (정수, 긴 포인터) 모델 size_t에서 32 비트입니다. 64 비트 또는 공통 LP64 (long, pointer) 모델 size_t는 64 비트입니다 (정수는 여전히 32 비트 임).

다른 모델도 있지만 g ++에서 사용하는 모델입니다 (최소한 기본적으로)


15
size_t일반적으로 포인터와 크기가 반드시 동일하지는 않습니다. 포인터는 메모리의 임의의 위치를 ​​가리킬 수 있어야합니다. size_t가장 큰 단일 객체의 크기를 나타낼만큼 충분히 커야합니다.
Keith Thompson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.