programing

C / C ++의 고정 길이 데이터 유형

nasanasas 2020. 10. 27. 08:18
반응형

C / C ++의 고정 길이 데이터 유형


같은 데이터 유형의 크기는 int플랫폼에 따라 다를 수 있다고 들었습니다 .

내 첫 번째 질문은 : 프로그램 int이 4 바이트 라고 가정 하지만 다른 플랫폼에서는 2 바이트라고 가정하면 누군가가 어떤 예를 들어 올릴 수 있습니까?

내가 가진 또 다른 질문은 관련이 있습니다. 나는 사람들이 일부이 문제를 해결 알고 typedefs당신이 같은 변수를 가지고있는 것처럼, u8, u16, u32플랫폼에 관계없이의, 8 비트, 16 비트, 32 비트 보장된다 - - 내 질문에, 어떻게이 일반적으로 얻을 수 있습니까? (저는 stdint라이브러리의 유형을 언급하는 것이 아닙니다. 수동으로 궁금합니다. 플랫폼에 관계없이 일부 유형이 항상 32 비트라고 강제 할 수있는 방법은 무엇입니까?)


플랫폼에 관계없이 8 비트, 16 비트, 32 비트로 보장되는 u8, u16, u32와 같은 변수가있는 것처럼 사람들이 일부 typedef로이 문제를 해결한다는 것을 알고 있습니다.

특정 크기 유형이없는 일부 플랫폼이 있습니다 (예 : char 크기가 16 비트 인 TI의 28xxx). 이러한 경우 8 비트 유형을 가질 수 없습니다 (정말로 원하지 않는 한 성능 저하가 발생할 수 있음).

이것은 일반적으로 어떻게 달성됩니까?

일반적으로 typedef를 사용합니다. c99 (및 C ++ 11)에는 헤더에 이러한 typedef가 있습니다. 따라서 사용하십시오.

프로그램이 int가 4 바이트라고 가정하지만 다른 플랫폼에서는 2 바이트라고 가정 할 때 누군가가 어떤 예를 가져올 수 있습니까?

가장 좋은 예는 유형 크기가 다른 시스템 간의 통신입니다. 하나에서 다른 플랫폼으로 int 배열을 보내는데, 여기서 sizeof (int)는 두 가지에서 다릅니다. 하나는 극도로주의해야합니다.

또한 32 비트 플랫폼의 바이너리 파일에 int 배열을 저장하고 64 비트 플랫폼에서이를 재 해석합니다.


C 표준의 이전 반복에서는 일반적으로 컴파일러에 전달 typedef#define문자열을 기반으로 16 비트 유형 (예 : 16 비트 유형)을 확보하기 위해 고유 한 명령문을 작성했습니다. 예 를 들면 다음과 같습니다.

gcc -DINT16_IS_LONG ...

요즘 (C99 이상) uint16_t에는 정확히 16 비트 너비의 부호없는 정수 와 같은 특정 유형이 있습니다 .

를 포함 stdint.h하면에 문서화 된대로 정확한 비트 너비 유형, 최소한 그 너비 유형, 주어진 최소 너비의 가장 빠른 유형 등을 얻을 수 C99 7.18 Integer types <stdint.h>있습니다. 구현에 호환 가능한 유형이있는 경우이를 제공해야합니다.

또한 inttypes.h이러한 새로운 유형 ( printfscanf형식 문자열) 의 형식 변환을위한 다른 깔끔한 기능을 추가하는 것도 매우 유용합니다 .


첫 번째 질문 : Integer Overflow .

두 번째 질문의 경우 : 예를 들어 4 바이트 인 typedef플랫폼에서 부호없는 32 비트 정수에 대해 int다음을 사용합니다.

 typedef unsigned int u32;

int2 바이트이고 long4 바이트 인 플랫폼에서 :

typedef unsigned long u32;

이런 식으로 유형을 교차 플랫폼으로 만들기 위해 하나의 헤더 파일 만 수정하면됩니다.

플랫폼 별 매크로가있는 경우 수동으로 수정하지 않고도이 작업을 수행 할 수 있습니다.

#if defined(PLAT1)
typedef unsigned int u32;
#elif defined(PLAT2)
typedef unsigned long u32;
#endif

C99 stdint.h가 지원되는 경우 선호됩니다.


첫째 : 같은 종류의 폭에 의존하는 절대 쓰기 프로그램 short, int, unsigned int, ...

기본적으로 : "표준에 의해 보장되지 않는 경우 너비에 의존하지 마십시오".

진정으로 플랫폼에 독립적이고 예를 들어 값 33000을 부호있는 정수로 저장하고 싶다면,이 값 을 유지할 것이라고 가정 수는 없습니다int . An int은 적어도 -32767to 32767또는 -32768to 범위 가지고 있습니다 32767(1/2 보수에 따라 다름). 즉, 비록 그냥 충분 일반적으로 32 비트 및 로요 필요한이 값에 대해 33000.을 저장하므로 할 수 >16bit따라서 당신은 단순히 선택을 입력 int32_t하거나 int64_t. 이 유형이 존재하지 않는 경우 컴파일러는 오류를 알려 주지만 침묵의 실수는 아닙니다.

둘째 : C ++ 11은 고정 너비 정수 유형에 대한 표준 헤더를 제공합니다. 이들 중 어느 것도 플랫폼에 존재한다는 보장은 없지만 존재하는 경우 정확한 너비가 보장됩니다. 참조 는 cppreference.com의이 기사를 참조하십시오. 종류는 형식으로 명명 int[n]_t하고 uint[n]_tn이다 8, 16, 32또는 64. 헤더를 포함해야합니다 <cstdint>. C헤더 물론이다 <stdint.h>.


일반적으로 문제는 번호를 최대로 사용하거나 직렬화 할 때 발생합니다. 덜 일반적인 시나리오는 누군가가 명시 적으로 크기를 가정 할 때 발생합니다.

첫 번째 시나리오에서 :

int x = 32000;
int y = 32000;
int z = x+y;        // can cause overflow for 2 bytes, but not 4

두 번째 시나리오에서는

struct header {
int magic;
int w;
int h;
};

그런 다음 fwrite로 이동합니다.

header h;
// fill in h
fwrite(&h, sizeof(h), 1, fp);

// this is all fine and good until one freads from an architecture with a different int size

세 번째 시나리오에서 :

int* x = new int[100];
char* buff = (char*)x;


// now try to change the 3rd element of x via buff assuming int size of 2
*((int*)(buff+2*2)) = 100;

// (of course, it's easy to fix this with sizeof(int))

If you're using a relatively new compiler, I would use uint8_t, int8_t, etc. in order to be assure of the type size.

In older compilers, typedef is usually defined on a per platform basis. For example, one may do:

 #ifdef _WIN32
      typedef unsigned char uint8_t;
      typedef unsigned short uint16_t;
      // and so on...
 #endif

In this way, there would be a header per platform that defines specifics of that platform.


I am curious manually, how can one enforce that some type is always say 32 bits regardless of the platform??

If you want your (modern) C++ program's compilation to fail if a given type is not the width you expect, add a static_assert somewhere. I'd add this around where the assumptions about the type's width are being made.

static_assert(sizeof(int) == 4, "Expected int to be four chars wide but it was not.");

chars on most commonly used platforms are 8 bits large, but not all platforms work this way.


Well, first example - something like this:

int a = 45000; // both a and b 
int b = 40000; // does not fit in 2 bytes.
int c = a + b; // overflows on 16bits, but not on 32bits

If you look into cstdint header, you will find how all fixed size types (int8_t, uint8_t, etc.) are defined - and only thing differs between different architectures is this header file. So, on one architecture int16_tcould be:

 typedef int int16_t;

and on another:

 typedef short int16_t;

Also, there are other types, which may be useful, like: int_least16_t


  1. If a type is smaller than you think then it may not be able to store a value you need to store in it.
  2. To create a fixed size types you read the documentation for platforms to be supported and then define typedefs based on #ifdef for the specific platforms.

can someone bring some example, what goes wrong, when program assumes an int is 4 bytes, but on a different platform it is say 2 bytes?

Say you've designed your program to read 100,000 inputs, and you're counting it using an unsigned int assuming a size of 32 bits (32-bit unsigned ints can count till 4,294,967,295). If you compile the code on a platform (or compiler) with 16-bit integers (16-bit unsigned ints can count only till 65,535) the value will wrap-around past 65535 due to the capacity and denote a wrong count.


Compilers are responsible to obey the standard. When you include <cstdint> or <stdint.h> they shall provide types according to standard size.

Compilers know they're compiling the code for what platform, then they can generate some internal macros or magics to build the suitable type. For example, a compiler on a 32-bit machine generates __32BIT__ macro, and previously it has these lines in the stdint header file:

#ifdef __32BIT__
typedef __int32_internal__ int32_t;
typedef __int64_internal__ int64_t;
...
#endif

and you can use it.


bit flags are the trivial example. 0x10000 will cause you problems, you can't mask with it or check if a bit is set in that 17th position if everything is being truncated or smashed to fit into 16-bits.

참고URL : https://stackoverflow.com/questions/20237451/fixed-length-data-types-in-c-c

반응형