32bit CPU 인 ARM 에서 개발하고 있을때,
아래와 같이 64비트 변수를 사용하려고 u_int64_t 타입을 사용할 경우, 문제 없이 동작되기를 기대하겠지만 잘 안되는 경우가 많다.
#include <stdio.h> #include <sys/types.h> int main(int argc, char *argv[]) { u_int64_t value1; value1 = 0xffffffffffffffff; printf("%lld\n", value1); return 0; }
위 코드를 아래처럼 컴파일을 해 보면
$ arm-none-linux-gnueabi-gcc -Wall -Werror -o test test.c cc1: warnings being treated as errors test.c: In function 'main': test.c:9: error: integer constant is too large for 'long' type
위와 같이 에러가 발생한다. 물론 -Werror 옵션을 제거하면 Warring 은 뜨겠지만 빌드는 될 것이다.
#typedef unsigned long long int uint64_t
$ arm-none-linux-gnueabi-gcc -Wall -Werror -std=gnu99 -o test test.c
ARM 쪽에서는 잘 빌드 되었는데, 이젠 X86_64 에서 printf 사용시 문제가 발생한다.
위의 에러 메시지에서 볼 수 있듯이
32bit 머신에서 uint64_t 는 unsinged long long int 인데,
64bit 머신에서 uint64_t 는 unsigned long int 이므로
printf("out : %lld\n", value); /* 32bit 머신에서는 OK, 64bit 머신에서는 fail */
printf("out : %ld\n", value); /* 32bit 머신에서는 fail, 64bit 머신에서는 OK */
인 상황이 벌어지게 된다.
우선 stdint.h 를 참조하여 코드를 아래와 같이 묶어 주었다.
#include <stdio.h> #include <sys/types.h> int main(int argc, char *argv[]) { u_int64_t value1; value1 = 0xffffffffffffffff; #if __WORDSIZE == 64 printf("%ld\n", value1); #else printf("%lld\n", value1); #endif return 0; }
위와 같은 방식을 사용해도 되고 아래처럼 type casting 을 사용해도 된다. 아래 방식이 더욱 안정적으로 동작할 것이다.
#include <stdio.h> #include <sys/types.h> int main(int argc, char *argv[]) { u_int64_t value1; value1 = 0xffffffffffffffff; printf("%lld\n", (long long unsigned int)value1); return 0; }
이런 문제는 특히, 멀티플랫폼을 지원하는 SW 개발시에 발생할 가능성이 크다. 처음부터 멀티 플랫폼 지원을 예상하여 작성하면 향후 알 수 없는 문제 발생을 줄일 수 있다.
'development' 카테고리의 다른 글
[driver] ipTime N150UA-4dBi (8) | 2014.09.16 |
---|---|
[program] unused variable 문제 (0) | 2013.08.02 |
[u-boot] RPC : sendmsg returned error 101 (0) | 2013.07.19 |
[Kernel] Kbuild system (0) | 2013.07.12 |
[kernel] __read_mostly????? (0) | 2013.05.08 |