2016-10-06 16 views
5

일부 배경 :C89에서 고정 너비 정수를 사용하기 위해 잘 확립되고 표준화 된 방법이 있습니까?

헤더 stdint.h is part of the C standard since C99. 여기에는 부호가 있거나 부호가없는 8, 16, 32 및 64 비트 정수가 될 수있는 typedef가 포함됩니다. 이 헤더는 C89 표준의 일부는 아니지만, 은 내 데이터 유형이 알려진 길이인지 확인하기 위해 직접적으로 방법을 찾지 못했습니다.

실제 주제

(C89로 작성) SQLite는 64 비트 정수를 정의하지만, 나는 그것이 설득력 찾을 수없는 방법 다음 코드는에 도착. 즉, 나는 그것이 모든 곳에서 효과가있을 것이라고 생각하지 않습니다. 모두의 최악의, 그것은 자동으로 실패 할 수 있습니다 :

  • 은 "문자"데이터 유형은 8 비트 길이 있음을 확인, it's not guaranteed to be 이후 :

    /* 
    ** CAPI3REF: 64-Bit Integer Types 
    ** KEYWORDS: sqlite_int64 sqlite_uint64 
    ** 
    ** Because there is no cross-platform way to specify 64-bit integer types 
    ** SQLite includes typedefs for 64-bit signed and unsigned integers. 
    */ 
    #ifdef SQLITE_INT64_TYPE 
        typedef SQLITE_INT64_TYPE sqlite_int64; 
        typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; 
    #elif defined(_MSC_VER) || defined(__BORLANDC__) 
        typedef __int64 sqlite_int64; 
        typedef unsigned __int64 sqlite_uint64; 
    #else 
        typedef long long int sqlite_int64; 
        typedef unsigned long long int sqlite_uint64; 
    #endif 
    typedef sqlite_int64 sqlite3_int64; 
    typedef sqlite_uint64 sqlite3_uint64; 
    

    그래서, 이것은 내가 지금까지 뭘했는지입니다 . 전 처리기 변수 "CHAR_BIT"가 8과 같지 않으면 컴파일이 실패합니다.

  • "char"은 8 비트 길이가 보장되므로 여러 개의 서명되지 않은 문자 배열을 포함하는 구조체를 만듭니다. 정수.
  • 필자는 내 데이터 유형에 대해 "연산자"기능을 작성합니다. 덧셈, 곱셈, 나눗셈, 모듈로, 문자열과 변환/변환 등

헤더 파일에서이 과정을 추상화했습니다. 이것이 내가 알고있는 것과 함께 할 수있는 최선의 방법이지만, 이것을 달성하기위한보다 간단한 방법.

휴대용 C 라이브러리를 작성하고 싶습니다.

+2

한 가지 해결책은 컴파일러가 제공하는 데이터 크기가 예상 한 것임을 확인하기 위해 컴파일 타임 어설 션을 사용하는 것일 수 있습니다. 예를 들면 다음과 같습니다. http://www.pixelbeat.org/programming/gcc/static_assert.html – David

+4

현대적인 C 기능을 원하면 고대 C가 아닌 최신 C 코드를 작성하십시오. – Olaf

+0

기본 정수 유형은 대개 런타임의 일부입니다 glibc와 같은 지원 라이브러리. 이러한 라이브러리는 결코 이식성이 뛰어나지 않도록 설계되었습니다. 이식성을 높이려는 노력은 대개 필요한 경우 다른 대상에 대해 같은 방법을 다른 방법으로 구현합니다. – user3528438

답변

10

먼저, <stdint.h>을 제공하지 않는 구현을 실제로 지원해야하는지 여부를 자문해야합니다. 1999 년에 표준화되었으며 많은 C99 이전 구현도이를 확장으로 제공 할 가능성이 큽니다.

ISO C 표준위원회의 구성원 인 Doug Gwyn은 C89/C90과 호환되는 C9x 용 새 헤더 (C99가 알려짐) 구현을 만들었습니다. 헤더는 공개되어있어 이식성이 있어야합니다.

http://www.lysator.liu.se/(nobg)/c/q8/index.html

는 (내가 알고있는 것처럼, 이름이 "Q8은"특별한 의미가 없다, 그는 단지 합리적으로 짧고 고유의 검색어로 선택했다.) 정수 타입의

+1

구식 표준의 본질은 상기 표준과 만 호환되는 * 어딘가에 구형 플랫폼이 있다는 것입니다. 개발자는 이식성을 극대화하려는 이유를 스스로에게 묻지 않아도됩니다. – jrodatus

+2

@jrodatus : 개발자는 * 모든 디자인 결정에 대한 이유를 스스로 물어야합니다. 예를 들어, C는 1989 년에 프로토 타입을 도입했습니다. 내가 그렇게 할 필요가 없다면 구식 함수 선언을 사용하는 코드를 작성하지 않을 것이다. ''에도 동일하게 적용됩니다. 유일한 차이점은 28 년 전인 18 년 전부터 소개 된 것입니다. 물론 이러한 종류의 이식성이 필요하다면, 가지고 있는지 확인하기 위해 무엇이든해야합니다. –

+0

그건 완벽하게 이해할 수 있습니다. 설명해 주셔서 감사합니다. – jrodatus

1

하나 오히려 불쾌한 특질을 C에서 많은 "현대"구현물은 적어도 하나의 정수 크기에 대해 동일한 비트 표현과 두 개의 호환되지 않는 부호없는 유형이있는 크기가 서로 호환되지 않는 두 가지 서명 된 유형을 갖게됩니다. 가장 일반적으로 유형은 32 비트 "int"및 "long"또는 64 비트 "long"및 "long long"입니다. "고정 크기"유형은 일반적으로 표준 유형 중 하나로 별명을 지정하지만 구현 유형이 표준 유형과 일치하지 않습니다.

주어진 크기의 한 유형에 대한 액세스가 다른 유형의 객체에 영향을 미칠 수 있다고 가정하는 컴파일러는 표준의 작성자가 그렇게하도록 요구하지 않았습니다 (아마도 사람을 주문할 시점이 없었기 때문일 것입니다). 어쨌든 그들은 할 일을하고, 다른 컴파일러 작성자가 그렇게하기 시작하면, "허가"를 취소하는 것이 정치적으로 어렵다. 따라서 32 비트 "int"에 데이터를 저장하는 라이브러리와 32 비트 "long"에서 데이터를 읽는 라이브러리가있는 경우 올바른 동작을 보장하는 유일한 방법은 모두 별칭 분석을 사용하지 않도록 설정하는 것입니다 (아마도 gcc를 사용하는 동안 가장 안전한 선택) 또는 gratuitous 복사 작업을 추가하십시오 (gcc가 코드를 최적화하지 않고 코드 부재를 핑계로 사용하지 않도록주의하십시오 - 때로는 6.2로 수행).