Chap.2 : Types, Operators, and Expressions
2.7 Type Conversion(자료형 변환)
연산에 의한 자료형 변환
operator의 두 operands가 타입이 다르면 보통 narrow한 type이 wider한 type으로 변환된다.
float형 변수를 subscription으로 쓰는 등의 말도안되는 conversion은 에러를 일으킨다.
long -> short, float -> integer type으로의 변환 등 정보가 삭제되는, truncation이 일어나는 자료형은 컴파일러에서 warning을 내보내지만 error가 되지는 않는다.
주의 해야할 것 중 하나는
int s = '0'
은 에러가 아니라는 것이다. string은 character과 다르다. character은 엄연히 integer로써 다뤄지고, 그저 컴퓨터 내부의 ASCII code 법칙에 의해 string처럼 출력될 뿐이다.
character가 integer라는 것을 응용하면
// 소문자를 대문자로 바꾼다.
int lower(int c){
if(c >= 'A' && c <= 'Z')
return c + 'a' - 'A';
else
return c;
}
이런 코드를 쓸 수 있다. 물론 C standard library에서 같은 기능을 하는 tolower()를 제공하니 그걸 쓰면 되겠다.
비슷하게 if(c >= '0' && c <= '9')
등의 구문도 isdigit(c)
으로 바꿀 수 있다.
- relation operator에서의 자료형 변환
&& ||에 의한 연산 결과는 항상 0 혹은 1이 나온다.
d = c >= '0' && c <= '9'
와 같은 경우 c
가 float형이어도 d는 integer가 나온다.
+
,*
연산자
lower type이 higher type이 된다. 이에 관한 rule은 appendix A section 6에서 볼 수 있다.
unsigned 표시가 없다면 아래와 같은 rule을 따른다.
long double이 있으면 다른 operand를 long double로 바꾼다.
없다면, double이 있으면 다른 operand를 double로 바꾼다.
없다면, float이 있으면 다른 operand를 float로 바꾼다.
없다면, char과 short는 int로 바꾼다.
마지막으로 long이 있으면 다른 operand를 long로 바꾼다.
원서에는 이렇게 적혀있는 부분이 있는데, 무슨 의미인지 잘 모르겠다.
notice that float in an expression are not automatically converted to double; this is a change from the original definition
(표현식의 float는 자동으로 double로 변환되지 않습니다. 이것은 원래 정의에서 변경된 것입니다.)
- signed, unsigned 간의 비교는 machine-dependent하다. 이 비교는 각 정수자료형의 크기에 영향을 받는다.
suppose that int is 16 bits and long is 32 bits. Then -1L < 1U, because 1U, which is an int, is promoted to a signed long. But -1L > 1UL, because -1L is promoted to unsigned long and thus appears to be a large positive number.
(int가 16 비트이고 long이 32 비트라고 가정합니다. int 인 1U가 signed long으로 승격되기 때문에 -1L <1U입니다. 그러나 -1L> 1UL은 -1L이 unsigned long으로 승격되어 더 큰 양수인 것처럼 보이기 때문입니다.)
=
연산자에서의 자료형 변환
우측이 좌측의 자료형으로 변환된다.
int i;
char c;
i = c;
c = i;
character -> int는 위에서 아래에서 언급할 것과 같이, 그 부호처리가 machine dependent하게 처리된다.
int -> character의 경우 excess high-order bits(char 자료형의 크기를 넘는 큰 비트들)를 삭제한다.
float, int형 간의 자료형 변환
float x;
int i;
x = i
i = x
이 경우, float -> int는 truncation(정수부 밑 삭제)이 일어난다.
float x;
double y;
x = y
y = x
이 경우, double->float은 그 구현 방법에 따라 rounded될 수도 있고, truncation(float의 소수 표기 한계점 밑 삭제)이 일어날 수도 있다.
- argument에서의 자료형 변환
function prototype에 관한 선언이 없을 때, char/short는 int가 되고, float은 double이 된다.
이를 이용해서 function의 parameter가 char, float로 호출된 함수를 function argument가 int double이 되게 선언할 수 있다.
근데 그냥 자료형이 같도록 조절해야 warning없이 컴파일 할 수 있지 않을까 싶다.
자료형 변환 시 부호처리
char이 int로 변환될 때, negative integer가 나올 수도 있나?
machine에 따라 달라진다.
어떤 machine에선 sign extension에 의해 음수인 char이 그대로 음수인 int가 될 수도 있고(sign extension에 관한 영상),
어떤 machine에선 char의 leftmost bit에 0을 추가해줘서 항상 양수가 되게 할 수도 있다.
C언어의 경우, 기계의 표준 인쇄 문자 집합의 모든 문자가 음수가되지 않도록 보장하므로 이러한 문자는 항상 표현식에서 양수가 된다. ASCII code도 extended된 것이 아니라면 7bit로 표현이 가능하므로 음수로 변환되는 것을 걱정할 일이 없다.
extended 경우와 같이 아예 양수만 필요한 경우를 위해 C언어에선 signed unsigned 두개의 자료형을 제공한다.
물론 그냥 char이 아닌 int를 사용하는 것으로 해결가능하다.
type casting 연산자
explicit type conversion이라고도 한다.(type-name) expression
과 같이 적어주면 되겠다. 이렇게 하면 expression의 type이 괄호안의 type으로 변환된다.
the precise meaning of a cast is as if the expression were assigned to a variable of the specified type, which is then used in place of the whole construction.(cast의 정확한 의미는 표현식이 지정된 유형의 변수에 할당된 다음, 전체 구성 대신 사용되는 것과 같습니다.)
sqrt()함수의 경우 double 자료형을 받는데, int형 자료형을 받는다고 하면 이렇게 표기할 수 있다.sqrt((double) n)
변수 n
그 자체는 변화하지 않는다.
물론 function call에서 자동으로 자료형 변환이 일어나므로, sqrt(2)
는 sqrt((double) 2)
가 자동으로 처리된다.
종합 예시
unsigned long int next = 1;
// 의사 난수 생성 함수
int rand(void){
next = next * 1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
}
// rand()를 위한 시드를 받는 함수
void srand(unsigned int seed){
next = seed;
}
return (unsigned int)(next/65536) % 32768;
에서 explicit type casting이 일어난다.