2009-05-07 2 views
1

다음 코드 고려 : C++에서일반적인 산술 변환 - 더 나은 규칙 집합입니까?

void f(byte x) {print("byte");} 
void f(short x) {print("short");} 
void f(int x) {print("int");} 

void main() { 
    byte b1, b2; 
    short s1, s2; 

    f(b1 + b2); // byte + byte = int 
    f(s1 + s2); // short + short = int 
} 

는, C 번호는, D, 및 Java는 모두 기능은 "INT"과부하로 결의를 호출 ... 이미 인식이있다 "사양에서"를, 그런데 왜 이런 식으로 언어가 설계 되었습니까? 나는 더 깊은 이유를 찾고있다.

byte + byte --> byte 
sbyte + sbyte --> sbyte 
byte + sbyte --> short 
short + short --> short 
ushort + ushort --> ushort 
short + ushort --> int 
// etc... 

이 불편 코드 등 short s3 = (short)(s1 + s2)을 제거하는 것처럼, 상기 결과는 예를 들어, 두 피연산자의 모든 가능한 값을 나타낼 수 작은 종류로 나에게

, 그것은 의미가 있습니다 IMO가 훨씬 더 직관적이고 이해하기 쉽습니다.

C의 요즘 남긴 유산인가요? 아니면 현재의 행동에 대한 더 나은 이유가 있습니까?

+0

"void main()"이있는 프로그램은 C 및 C++ 표준에 의해 정의되지 않았으므로 그 프로그램에 대해 불평 할 이유가 없습니다. 표준화 된 비헤이비어를 논의하려면 "int main()"을 사용하십시오. –

+0

C 및 C++ 외에 다른 언어를 언급했습니다. 그것을 단지 의사 코드로 생각하면됩니다. 약간의 변경 (예 : void, int to char, byte to char, printf 등으로 변경)과 같은 모든 C 언어로 컴파일되고 설명 된 동작을 나타냅니다. 물론 수정되지 않은 소스 파일이 언급 된 모든 언어로 컴파일 될 것이라고 기대하지 않았습니까? – zildjohn01

답변

2

this MSDN blog post에서 인용 :

바이트 B = 32; 바이트 c = 240; int i = b + c; // 나는 무엇인가?

이 환상 세계에서 i 의 값은 16이됩니다! 왜? + 연산자에 대한 두 개의 피연산자 인 은 모두 바이트이므로 합계 "b + c"는 바이트로 계산되므로 정수가 오버플로되어 16이됩니다. (I 앞서 지적과 같이, 정수 오버플 새로운 보안 공격 벡터이다.) 유사하게

,

INT J = -b;

과 같은 이유로 인해 값이 224 이고 값이 아닌 j가됩니다.

정말 원하는 것입니까?

...

그래서 아무리 당신이 그것을 슬라이스하는 방법, 당신은 성가신 캐스트를 삽입해야 할 것입니다 없습니다. 언어 측면에 오류가 있습니다. 은 (누설이 문제가되지 않는 을 알고있는 캐스트를 넣으십시오) 오류가있는 곳에서 오류가 없음을 알 수 있습니다. 귀하의 급여 부서가 월이 의 끝에 합산되지 않는 이유를 묻는 메시지가 까지 전송됩니다.

또한이 캐스트를 추가하면 추가 입력이 필요하다는 것을 알 수 있습니다. JIT (또는 정적 컴파일러 자체)가 산술 연산을 기본 프로세서 명령어로 줄이면 아무런 영리가 없습니다. 숫자가 int 또는 byte으로 취급되는지 여부가 결정됩니다.

그러나 이것은 좋은 질문입니다. 그러나 명백한 것은 아닙니다. 희망은 그 이유를 분명히합니다.

+1

1 년 후이 문제가 다시 돌아오고 있습니다 ... 나는 기사 자체보다는 기사에 대한 의견에 훨씬 더 공감합니다. 오 잘, 적어도 나는 디자인 결정을 이해한다. – zildjohn01

+0

래핑 유형이 다른 숫자 유형으로 변환 할 수 없지만 추가 될 때 가장 작은 음이 아닌 숫자를보고하는 함수 또는 속성이있는 규칙과 함께 별개의 "래핑"및 비 랩핑 정수 유형이있는 방법은 어떻습니까? 주어진 값을 산출하거나, 0에 더해질 때 주어진 값을 산출 할 수있는 최소 크기의 값을 산출 할 것이다. 그러면'(240wb + 255wb) .AsUnsigned'는 239가되고'(240wb + 255wb) .AsSigned'는 -17이됩니다. 나는 컴파일 된 모든 케이스가 명확한 예상 된 행동을 산출 할 것이라고 생각한다. – supercat

0

더 나은 규칙 세트 IMHO는 이동 연산자가 상수 시프트 값 (가변 시프트 양에 대해 시프트 함수 사용)에서만 사용될 수 있다고 가정하면 산술 표현식의 결과는 항상 가능한 가장 큰 부호가 있거나 서명되지 않은 유형으로 처리되었지만, 올바른 결과를 제공하기 위해 정적으로 보장 될 수 있습니다 (가장 큰 부호 유형이 충분하지 않을 수있는 경우에는 약간 까다로운 규칙이 적용됩니다). 제공된 시프트 피연산자는 단지 상수가 될 수 있습니다. 컴파일 할 때 피연산자 중 가장 큰 의미있는 값이 무엇인지 쉽게 판단 할 수 있습니다. 따라서 컴파일러가 연산자의 결과를 사용하는 방법을 보지 못하는 이유가 없습니다 연산자의 구현을 결정할 때.