c에서 "~" 연산자의 (암시적) 타입변환에 대한 질문입니다.
글쓴이: ktd2004 / 작성시간: 목, 2007/02/22 - 1:29오후
다음과 같은 소스를 테스트했습니다.
int main(void) { unsinged char a = 0xF0; unsinged char b = 0x0F; if( a == ~b) { printf("equal\n"); } else { printf("not equal\n"); } return 0; }
결과는 "not equal"입니다.
이 문제로 반나절을 보냈습니다.
제가 처음에 코딩을 할 때는
* "unsigned char" 타입을
* "~"연산자로 걸고
* "unsigned char"와 비교를 하면
"equal"이 출력될 것으로 예측했습니다.
"if( a == ~b)" 부분에 대한 정확한 분석/정보 부탁드립니다.
미리 답변 감사드립니다.
Forums:
흠 내부적으로 type casting 이 일어나는것 같네요.
다음을 실행해보면 확인 가능할겁니다.
결과:
f0
fffffff0
equal
비교전에 미리선언한 변수선언형으로 casting해주면 equal로 결과가 나옵니다.
~ 연산자를 그냥 쓰면 사용하는 architecture의 기본형(위에서는 32bit 형식)로 형변환이 되는것 같네요.
참고하시기
참고하시기 바랍니다.
http://groups.google.co.kr/group/han.comp.lang.c/msg/cb30ec78db03cf81
--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)
--
Jun, Woong (woong at gmail.com)
http://www.woong.org
참부해 주신 링크 잘
참부해 주신 링크 잘 보았습니다.
링크를 보고 제가 이해한 중요한 점은 다음과 같습니다.
* ~ 연산자의 피연산자는 signed int로 형변환된다.
따라서 원문은 다음과 같은 순서로 해석된다고 이해했습니다.
* 제가 이해한 내용이 맞는지요?
* 그럼 원문을 다음과 같이 변경해서 사용하면 별 문제(이식성/표준)가 없는지요?
답변 감사드립니다.
모든 논리, 산술 연산은 int형으로 연산된다고 얼핏들은것 같습니다.
보통 int형은 해당 머신의 register의 사이즈와 같다고 봅니다.
당연히 register크기와 같은 자료형을 사용할 경우 속도면에서나 효율적이기 때문에 그렇게 만들었겠죠.
a == ~b 이구문에서는 2번의 연산이 일어납니다.
1번째 비트연산.
2번째 ==연산 ==연산은 내부적으로 a-b값이 0인지 판별하기 때문에 일반 산술연산으로 봐도 무방합니다.
a,b는 연산을 위해서 4바이트로 확장이 됩니다.
a -> 0x000000F0
b -> 0x0000000F
여기에서 만약 signed char이었다고 하면...
a -> 0xFFFFFFF0
b -> 0x0000000F
이런식으로 확장이 일어나겠죠 ^^;
이 이후에 연산을 하시면 설명이 되겠죠?
(unsigned char)a == (unsigned char)~b
(unsigned char)로 강제 캐스팅을 하게되면...
우항 b의 경우 int로 확장이 되어 ~연산을 한후 (unsigned char)로 강제 캐스팅이 되어 상위값을 짜릅니다.
그리고 == 연산을 위해
다시 a항과 b항이 모두 int로 확장되어야 겠죠?
ㅎㅎ 정확한건 아니니 비판적으로 수용하시길...
------------------------------
lol
> (unsigned char)a ==
> (unsigned char)a == (unsigned char)~b
> (unsigned char)로 강제 캐스팅을 하게되면...
> 우항 b의 경우 int로 확장이 되어 ~연산을 한후 (unsigned char)로 강제 캐스팅이 되어 상위값을 짜릅니다.
>
http://groups.google.co.kr/group/han.comp.lang.c/msg/442779a7378e556a
--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)
--
Jun, Woong (woong at gmail.com)
http://www.woong.org
> 참부해 주신 링크
> 참부해 주신 링크 잘 보았습니다.
> 링크를 보고 제가 이해한 중요한 점은 다음과 같습니다.
> * ~ 연산자의 피연산자는 signed int로 형변환된다.
>
보다 정확히는 "integral promotion 이 적용된다"가 맞습니다.
대부분의 구현체에서 UCHAR_MAX <= INT_MAX 이기에 int 로 진급이 이루어
지지만, (일부 DSP 를 위한 freestanding 환경에서처럼) UCHAR_MAX >
INT_MAX 라면 int 가 아닌 u-int 로 진급이 이루어집니다. 예를 들어, ~
가 적용되는 피연산자의 type 이 u-char 가 아니라 u-short 이고,
USHRT_MAX == UINT_MAX 인 환경이라면 역시 int 가 아닌 u-int 로 진급
됩니다. 여기서는 문제가 되는 경우인 int 로 진급되는 경우만을 이야기
하도록 하겠습니다.
> 따라서 원문은 다음과 같은 순서로 해석된다고 이해했습니다.
>
> if( 0xF0 == ~0x0F) // 원문
> if( 0xF0 == ~0x0000000F) // "~" 연산자의 피연산자가 signed int로 형변환
> if( 0xF0 == 0xFFFFFFF0) // "~" 연산자 적용
> if( 0x000000F0 == 0xFFFFFFF0) // "unsigned char"가 "unsigned int"로 형변환
>
상수를 16진 정수 상수 형태로 쓸 경우 연산이 실제로는 "값"에 적용된다
는 사실이 가려질 수 있습니다. 보다 분명한 설명을 위해 아래와 같이
기술하겠습니다.
> * 제가 이해한 내용이 맞는지요?
주요한 차이점은 int 형의 값 0x0000000F 에 ~ 를 적용한 결과가 모든
환경에서 0xFFFFFFF0 으로 나타낼 수 없다는 것(!)과, 그 이후 값을
비교할 때 좌측 피연산자는 u-int 가 아닌 int 로 변환된 이후 상등
비교 연산이 적용된다는 것입니다.
> * 그럼 원문을 다음과 같이 변경해서 사용하면 별 문제(이식성/표준)가 없는지요?
>
> if( a == (unsigned char)~b)
>
문제의 핵심은 비트 연산자를 항상 무부호 정수형에 적용되도록 하는 것
입니다. 이 경우 ~ 는 어차피 b 가 갖는 type (u-char) 의 진급된 type
(int) 에 적용되고 그 결과는 구현체 의존적인 값(b 의 값이 양수일 때
~ 는 sign bit 에도 영향을 주므로 ~ 연산 적용 결과는 음수)이 되며, 그
값을 다시 u-char 형으로 변환(음수를 u-char 로 변환하는 행동은 명확히
정의되어 있으나 그 음수값 자체에 이식성이 없기 때문에 u-char 로 변환
이후의 결과에도 이식성이 없음)해 a 와 비교하는 것에 불과합니다 - 제가
링크해드린 글 이외에 동일 thread 의 다른 글들도 한번 보시기 바랍니다.
http://groups.google.co.kr/group/han.comp.lang.c/browse_frm/thread/149c912a26aed543
이식성을 얻기 위해선 아래와 같이 수행해야 합니다.
이 경우 b 를 int 가 아닌 무부호 정수형으로 변환한 상태에서 ~ 를 적용
하며 이를 다시 unsigned char 로 변환하는 것은 모든 환경에서 상위 비트
를 잘라내는 결과를 보입니다.
다시 한번 강조드리지만, 핵심은 비트 연산 적용 시점에 피연산자의 type
을 더이상 implicit conversion 이 적용되지 않는 무부호 정수형으로
만들어 주는 것입니다.
--
Jun, Woong (woong at gmail.com)
http://www.woong.org
댓글 달기