다른 언어와 비교하여 C의 흥미로운 특징은 많은 데이터 유형이 절대 용어로 지정되지 않고 대상 아키텍처의 단어 크기를 기반으로한다는 것입니다. 이렇게하면 특정 유형에 문제가있는 컴퓨터 에서 언어 를 사용하여 코드를 작성할 수 있지만 다른 아키텍처에서 일관되게 실행되는 코드를 설계하는 것은 매우 어렵습니다. 코드를 고려하십시오 :
uint16_t ffff16 = 0xFFFF;
int64_t who_knows = ffff16 * ffff16;
int
16 비트 (여전히 작은 마이크로 컨트롤러에서도 마찬가지) 인 아키텍처 에서이 코드는 잘 정의 된 동작을 사용하여 1의 값을 할당합니다. int
64 비트 인 컴퓨터에서는 잘 정의 된 동작을 사용하여 4294836225라는 값을 할당합니다. int
32 비트 인 컴퓨터에서는 -131071의 값을 할당 할 수 있습니다 (구현 정의 또는 정의되지 않은 동작인지 알 수 없음). 코드가 명목상 "고정 크기"유형으로 가정 된 것을 제외하고는 아무것도 사용하지 않더라도, 표준은 오늘날 사용중인 두 가지 다른 종류의 컴파일러가 두 가지 다른 결과를 산출하고 오늘날 많은 인기있는 컴파일러가 1/3을 산출 할 것을 요구합니다.
이 특정 예제는 실제 코드에서 두 개의 16 비트 값의 곱을 64 비트 값에 직접 할당 할 것으로 기대하지는 않지만 세 가지 방법으로 정수를 보여주는 간단한 예로 선택되었습니다. 프로모션은 수정 된 크기의 부호없는 유형과 상호 작용할 수 있습니다. 부호없는 유형의 수학을 수학 정수 산술 규칙에 따라 수행해야하는 실제 상황과 모듈 식 산술 규칙에 따라 수행해야하는 상황, 실제로는 그렇지 않은 상황이 있습니다. 상관 없습니다. 체크섬과 같은 많은 실제 코드는 uint32_t
산술 래핑 모드 2³² 및 임의의 수행 능력에 의존합니다uint16_t
(정의되지 않은 동작을 트리거하는 것과는 대조적으로) 정확한 모드 65536으로 정의 된 최소한의 산술 및 결과를 얻습니다.
이 상황은 분명히 바람직하지 않은 것처럼 보이지만 (64 비트 처리가 많은 목적을 위해 표준이됨에 따라 더 커질 것임), 내가 관찰 한 것으로부터 C 표준위원회는 이미 주목할만한 제작에 사용 된 언어 기능을 도입하는 것을 선호합니다 환경을 "처음부터"발명하는 것이 아니라 C 언어에 대한 주목할만한 확장이있어 코드가 유형을 저장하는 방법뿐만 아니라 승격 가능성이있는 시나리오에서 어떻게 동작해야 하는지를 지정할 수 있습니까? 컴파일러 확장이 이러한 문제를 해결할 수있는 적어도 세 가지 방법을 볼 수 있습니다.
컴파일러에게 특정 "기본"정수 유형을 특정 크기로 설정하도록 지시하는 지시문을 추가합니다.
대상 아키텍처의 실제 유형 크기에 관계없이 머신 유형에 특정 크기가있는 것처럼 다양한 승격 시나리오를 평가하도록 컴파일러에 지시하는 지시문을 추가합니다.
추가 (특정 특성을 갖는 유형에 관계없이 근본적인 워드 크기 중, 개조-65536 포장 대수 링으로 동작해야하고, 다른 유형의 암시 적으로 변환해야하는 것이 아닌 예 선언을 유형을 선언하는 수단을 허용함으로써
wrap32
내지 An은int
을 수득한다 16 비트보다 큰지wrap32
여부에 관계없이 유형의 결과는 직접에int
추가하는 것이 불법이어야합니다 (둘 다 다른 것으로 변환 할 수 없으므로).wrap32
wrap16
내가 선호하는 것은 세 번째 대안이 될 수있다. 특이한 단어 크기를 가진 기계조차도 변수가 2의 거듭 제곱처럼 "포장"될 것으로 예상하는 많은 코드에서 작동 할 수 있기 때문이다. 컴파일러는 형식을 적절하게 작동시키기 위해 비트 마스킹 명령어를 추가해야 할 수도 있지만, 코드가 mod 65536을 감싸는 형식이 필요한 경우 소스 코드를 복잡하게 만드는 것보다 필요한 마스킹을 기계에서 생성하는 것이 좋습니다. 또는 단순히 그러한 마스킹이 필요한 기계에서 사용할 수없는 코드를 사용하십시오. 그러나 위의 수단 중 하나를 통해 또는 내가 생각하지 못한 수단을 통해 휴대용 행동을 달성하는 일반적인 확장이 있는지 궁금합니다.
내가 찾고있는 것을 명확히하기 위해 몇 가지가 있습니다. 가장 주목할만한 것 :
원하는 의미를 보장하기 위해 코드를 작성하는 방법에는 여러 가지가 있지만 (예 : 특정 크기의 부호없는 피연산자에 대해 수학을 수행하여 매크로를 정의하여 랩핑하거나 랩핑하지 않는 결과를 생성하거나) 원하지 않는 것을 방지하는 방법 의미론 (예 : 타입 이 승격되지 않는 컴파일러에서 유형
wrap32_t
을 조건부로 정의하고 해당 유형 이 승격 된 머신에서 컴파일을 실패 해야하는 코드가 실행되어 가짜 동작을 생성하는 것보다 낫다는 것을 파악), 미래의 언어 확장에 가장 유리한 코드를 작성하는 방법이 있다면, 그것을 사용하는 것이 내 자신의 접근 방식을 고안하는 것보다 낫습니다.uint32_t
uint32_t
wrap32_t
많은 정수 크기 문제를 해결하기 위해 언어를 확장하는 방법에 대한 확실한 아이디어가 있습니다. 코드가 다른 단어 크기의 컴퓨터에서 동일한 의미를 생성 할 수는 있지만 작성하는 데 상당한 시간을 소비하기 전에 그 방향으로 어떤 노력이 이미 수행되었는지 알기 위해.
나는 어떤 식 으로든 C 표준위원회 나 그들이 생산 한 일을 비방하는 것으로 여겨지기를 원하지 않는다. 그러나 몇 년 안에 "자연"승격 유형이 32 비트 인 시스템과 64 비트 인 시스템에서 코드가 올바르게 작동해야 할 것으로 예상됩니다. 나는 언어에 대한 약간의 확장 (C99 nnd C14 사이의 다른 많은 변경보다 더 겸손한)을 통해 64 비트 아키텍처를 효율적으로 사용하는 깔끔한 방법을 제공 할뿐만 아니라 거래와의 상호 작용을 촉진 할 수 있다고 생각합니다 표준을 지원하기 위해 역사적으로 뒤로 구부러진 "비정상적인 단어 크기"기계 (예 : 12 비트 char
를 가진 기계가 코드를 실행할 수있게하는 것)uint32_t
mod 2³²를 감싸기 위하여]. 미래의 확장이 취하는 방향에 따라, 오늘 작성된 코드가 기본 정수 유형이 "예상 된"동작을하는 오늘날의 컴파일러에서 사용할 수 있고 정수가있는 미래의 컴파일러에서도 사용할 수있는 매크로를 정의 할 수 있어야합니다. 유형은 기본적으로 다르게 동작하지만 필요한 동작을 제공 할 수있는 위치입니다.
int
보다 큰uint16_t
, 곱셈의 피연산자로 승격 될 수int
및 곱셈은 다음과 같이 수행 될 수int
곱셈, 결과int
값으로 변환 될 것이다int64_t
의 초기화who_knows
.