2010-04-30 2 views
2

나는 bignum 라이브러리를 작성 중이며 효과적인 데이터 유형을 사용하여 숫자를 나타내려고합니다. 특히 숫자에 대해서는 정수이고, 덧셈과 곱셈을 할 때 중간 표현에 대해서는 long (정수의 크기를 두 배로 엄격히 지정하면)입니다.stdint.h 및 ANSI printf 사용?

좀 C99 기능을 사용하여,하지만 난 내의 bignum 라이브러리에 다음 한 현재

ANSI C.을 준수하려고 노력한다

:

I가 절차를 작성하지 않은 것처럼
#include <stdint.h> 

#if defined(__LP64__) || defined(__amd64) || defined(__x86_64) || defined(__amd64__) || defined(__amd64__) || defined(_LP64) 
typedef uint64_t u_w; 
typedef uint32_t u_hw; 
#define BIGNUM_DIGITS 2048 
#define U_HW_BITS 16 
#define U_W_BITS 32 
#define U_HW_MAX UINT32_MAX 
#define U_HW_MIN UINT32_MIN 
#define U_W_MAX UINT64_MAX 
#define U_W_MIN UINT64_MIN 
#else 
typedef uint32_t u_w; 
typedef uint16_t u_hw; 
#define BIGNUM_DIGITS 4096 
#define U_HW_BITS 16 
#define U_W_BITS 32 
#define U_HW_MAX UINT16_MAX 
#define U_HW_MIN UINT16_MIN 
#define U_W_MAX UINT32_MAX 
#define U_W_MIN UINT32_MIN 
#endif 

typedef struct bn 
{ 
     int sign; 
     int n_digits; // #digits should exclude carry (digits = limbs) 
     int carry; 
     u_hw tab[BIGNUM_DIGITS]; 
} bn; 

bignum을 십진수로 쓰면 중간 배열을 분석하고 각 자릿수의 값을 printf해야합니다. 그러나 printf와 함께 사용할 변환 지정자는 모른다. 가급적이면 16 진수로 인코딩 된 숫자를 터미널에 쓰고 싶습니다.

근본적인 문제는 두 데이터 유형이 다른 데이터 유형보다 두 배 길고 표준 변환 지정자를 사용하여 printf와 함께 사용한다는 것입니다. int가 32 비트이고 long이 64 비트 인 경우에 이상적입니다. 그러나 전처리기를 사용하여 이것을 보장하는 법을 모르며, 표준 유형에만 의존하는 printf와 같은 함수를 사용할 시간이되면 더 이상 무엇을 알지 못합니다. 용도.

답변

3

당신은 도와 <inttypes.h>에서 매크로를 사용할 수 있습니다 그리고

#if defined(__LP64__) || defined(__amd64) || defined(__x86_64) || defined(__amd64__) || defined(__amd64__) || defined(_LP64) 
typedef uint64_t u_w; 
typedef uint32_t u_hw; 
#define BIGNUM_DIGITS 2048 
#define U_HW_BITS 16 
#define U_W_BITS 32 
#define U_HW_MAX UINT32_MAX 
#define U_HW_MIN UINT32_MIN 
#define U_W_MAX UINT64_MAX 
#define U_W_MIN UINT64_MIN 
#define PRI_U_HW PRIu32 // use for formatting a `u_hw` type 
#define PRI_U_W PRIu64 // use for formatting a `u_w` type 
#else 
typedef uint32_t u_w; 
typedef uint16_t u_hw; 
#define BIGNUM_DIGITS 4096 
#define U_HW_BITS 16 
#define U_W_BITS 32 
#define U_HW_MAX UINT16_MAX 
#define U_HW_MIN UINT16_MIN 
#define U_W_MAX UINT32_MAX 
#define U_W_MIN UINT32_MIN 
#define PRI_U_HW PRIu16 // use for formatting a `u_hw` type 
#define PRI_U_W PRIu32 // use for formatting a `u_w` type 
#endif 

:

printf("some u_w variable: %" PRI_U_W "\n", u_w_var);  
printf("some u_hw variable: %" PRI_U_HW "\n", u_hw_var); 

그들은 꽤 아니지만, 그들은 C99 그것을 수행하는 방법입니다.

+0

정의를 큰 따옴표로 묶으려고합니까? 어쨌든 편리한 팁. 나는 이것이 printf 맨 페이지에 기록 될 것이라고 생각했지만 C99가 어떻게 이러한 유형을 다루는 지 궁금해하고있었습니다. 감사합니다. – snap

+1

예제의 첫 번째 부분에서 정의되고있는 'PRI_U_HW'와'PRI_U_W'는 단순히 C99'PRIuXX' 값의 별명입니다. 문자열 리터럴이됩니다. 두 번째 코드 스 니펫의 2'printf()'예제에서와 같이)이를 사용하려면 따옴표 바깥에 따옴표를 사용하고 인접한 문자열 리터럴을 C의 ' 번역의 단계 6 '. 내가 말했듯이, 그것은보기 흉한 일입니다. –

+0

나는 본다. 그건 그렇고, 어쨌든이 프로세서 쓰레기를 피하고 int/long을 사용하는 것이 있다고 생각합니까? 저는 실제로 크기가 두 배인 두 가지 유형이 필요합니다. char 및 short 트릭을 할 것이라고 추측하지만 가능한 int/long/long long 같은 더 큰 데이터 형식을 사용하는 것이 좋습니다. – snap

1

ANSI C는 intlong 크기에 대한 보증을 제공하지 않으며 long long은 ANSI 유형이라고 생각하지 않습니다. C99를 사용하지 않거나 사용할 수없는 경우 유일한 안전하고 이식 가능한 솔루션은 sizeof을 사용하는 C 프로그램을 만드는 configure 스크립트를 작성하여 필요한 속성을 가진 정수 유형 쌍을 찾으십시오. 그 스크립트에서 printf 형식 매크로를 비롯한 매크로를 생성 할 수 있습니다.

C99을 사용하지 않는 이유는 C99 컴파일러가없는 이상한 플랫폼으로 이식하고 있기 때문일 수도 있습니다. 이 경우에는 무엇이 작동하는지 알아낼 수 있고 헤더에서 때 리고 이동성에 대해 걱정하지 않아도됩니다.

C99는보기 좋지 않지만 이러한 성가신 C 문제를 해결해줍니다.

+0

프로세스를 demystifying 주셔서 감사합니다. 나는 이것이 대부분의 autoconf 프로그램이하는 일이라고 생각한다. 수작업으로 제안 하시거나 열심히 할 수있는 도구가 있습니까? 나는 autoconf에 대해서만 알고 있으며, 작은 프로젝트를 시작하는 것이 복잡해 보인다. – snap

+0

@nn : 나는 GNU autotools에서 비명을 지르고있다. 필자는 수동으로 작성된 POSIX sh 스크립트를 제안합니다. –