Program Club

C 및 C ++에서 산술 연산 전에 short를 int로 변환해야하는 이유는 무엇입니까?

proclub 2020. 11. 8. 11:29
반응형

C 및 C ++에서 산술 연산 전에 short를 int로 변환해야하는 이유는 무엇입니까?


내가로부터받은 답변에서 이 질문에 , C ++가의 전환이 요구 사항을 상속 나타납니다 shortint에 대한 사용자의 두뇌를 선택 C. 월 I에서 산술 연산을 수행 할 때 이가 처음에 C에 도입? 왜 이러한 작업을 수행하지 short않습니까?

예를 들어 ( 주석에서 dyp의 제안에서 가져옴 ) :

short s = 1, t = 2 ;
auto  x = s + t ;

x유형은 int 입니다.


우리가 보면 국제 표준 프로그래밍 언어-C에 대한 이론적 근거 절에서 6.3.1.8 일반적인 산술 변환 이 (라고 강조 광산 향후 ) :

이러한 변환에 대한 표준의 규칙은 K & R의 규칙을 약간 수정 한 것입니다. 수정은 추가 된 유형과 가치 보존 규칙을 수용합니다. 절대적으로 필요한 것보다 "넓은"유형으로 계산을 수행하기 위해 명시 적 라이센스가 추가되었습니다.이 경우 정답을 더 자주 언급하는 것은 물론 더 작고 더 빠른 코드를 생성 할 수 있기 때문 입니다. 동일한 최종 결과가 얻어지는 한 as if 규칙에 따라 "더 좁은"유형으로 계산을 수행 할 수도 있습니다. 원하는 유형의 값을 얻기 위해 항상 명시 적 캐스팅을 사용할 수 있습니다.

제 6.3.1.8 로부터 초안 C99 표준 커버 일반적인 산술 변환 예를 들어 섹션 산술 표현식의 피연산자에 적용되는 6.5.6 첨가제 운영자는 말한다 :

두 피연산자에 산술 유형이있는 경우 일반적인 산술 변환 이 수행됩니다.

섹션 6.5.5 곱셈 연산자 에서도 유사한 텍스트를 찾을 수 있습니다. a의 경우 짧은 피연산자 먼저 정수 프로모션 섹션에서 적용 6.3.1.1 부울, 문자 및 정수 라고한다 :

int가 원래 유형의 모든 값을 나타낼 수있는 경우 값은 int로 변환됩니다. 그렇지 않으면 unsigned int로 변환됩니다. 이를 정수 프로모션이라고합니다 . 48) 다른 모든 유형은 정수 승격으로 변경되지 않습니다.

섹션에서 논의 6.3.1.1이론적 근거 또는 국제 표준 프로그래밍 언어-C 에 대한 정수 프로모션은 너무 긴 완전히 인용하는 것입니다 c를 실제로 더 재미있다, 나는 / 선택적으로 인용 B로 갈거야 :

구현은 서명되지 않은 보존과 가치 보존 으로 특징 지을 수있는 두 가지 주요 진영 으로 나뉩니다 .

[...]

부호 보존 방법은 서명되지 않은 INT에 두 개의 작은 부호없는 형식을 촉진 호출합니다. 이것은 간단한 규칙이며 실행 환경과 독립적 인 유형을 생성합니다.

값 보존 방법의 유형이 올바르게 서명되지 않은 INT로 그 유형을 촉진 그렇지 않으면 원래 유형의 모든 값을 표시하고, 할 수있는 경우 서명 INT로 그 유형을 촉진하기위한 통화. 따라서 실행 환경이 short를 int보다 작은 것으로 표현하면 unsigned short는 int가됩니다. 그렇지 않으면 unsigned int가됩니다.

서명되지 않은 유형과 더 큰 서명 된 유형 간의 암시 적 변환의 일관성없는 동작이 보여 주듯이 일부 경우에 예상치 못한 결과가 발생할 수 있습니다 . 이와 같은 예가 훨씬 더 많습니다. 대부분의 경우 이로 인해 작업이 예상대로 작동합니다.


코드가 실행되는 물리적 프로세서 아키텍처의 한계만큼 언어의 기능이 아닙니다. intC typer는 일반적으로 표준 CPU 레지스터의 크기입니다. 더 많은 실리콘은 더 많은 공간과 더 많은 전력을 차지하므로 대부분의 경우 산술은 "기본 크기"데이터 유형에서만 수행 할 수 있습니다. 이것은 보편적으로 사실이 아니지만 대부분의 아키텍처에는 여전히 이러한 제한이 있습니다. 즉, 두 개의 8 비트 숫자를 더할 때 프로세서에서 실제로 진행되는 것은 일종의 32 비트 산술에 이어 간단한 비트 마스크 또는 다른 적절한 유형 변환이 뒤 따르는 것입니다.


shortchar유형은 표준 종류의 "저장 유형"즉, 일부 공간을 절약하는 데 사용할 수있는 하위 범위에 의해 고려되지만 크기가 CPU에 대해 "부자연 스럽기"때문에 속도를 구매하지 않습니다.

특정 CPU에서 이것은 사실이 아니지만 좋은 컴파일러는 예를 들어 unsigned char에 상수를 추가하고 결과를 unsigned char에 다시 저장하면 unsigned char -> int변환을 수행 할 필요가 없다는 것을 알 수있을만큼 똑똑합니다 . 예를 들어 g ++의 경우 내부 루프에 대해 생성 된 코드

void incbuf(unsigned char *buf, int size) {
    for (int i=0; i<size; i++) {
        buf[i] = buf[i] + 1;
    }
}

그냥

.L3:
    addb    $1, (%rdi,%rax)
    addq    $1, %rax
    cmpl    %eax, %esi
    jg  .L3
.L1:

서명되지 않은 문자 추가 명령어 ( addb)가 사용 된 것을 볼 수 있습니다 .

짧은 정수 사이에서 계산을 수행하고 결과를 짧은 정수에 저장하는 경우에도 마찬가지입니다.


연결된 질문은 그것을 꽤 잘 다루는 것 같습니다. CPU는 그렇지 않습니다. 32 비트 CPU에는 32 비트 레지스터에 대해 설정된 기본 산술 연산이 있습니다. 프로세서는 원하는 크기로 작업하는 것을 선호하며 이와 같은 작업의 경우 작은 값을 기본 크기 레지스터에 복사하는 것이 저렴합니다. (x86 아키텍처의 경우 32 비트 레지스터는 16 비트 레지스터의 확장 된 버전 인 것처럼 이름이 지정됩니다 ( eaxto ax, ebxto bx등). x86 정수 명령어 참조 )

매우 일반적인 연산, 특히 벡터 / 부동 연산의 경우 다른 레지스터 유형 또는 크기에서 작동하는 특수 명령어가있을 수 있습니다. 짧은 것과 같은 경우 (최대) 16 비트의 0으로 패딩하는 것은 성능 비용이 거의 없으며 특수한 명령을 추가하는 것은 아마도 다이에 시간이나 공간의 가치가 없을 것입니다. 그들이 실제 공간을 차지할지 확신하지 못하지만 훨씬 더 복잡해집니다).

참고 URL : https://stackoverflow.com/questions/24371868/why-must-a-short-be-converted-to-an-int-before-arithmetic-operations-in-c-and-c

반응형