2010-11-04 170 views
4
#include <stdio.h> 
#include <inttypes.h> 

int main(void) 
{ 
    int8_t int8; 
    int16_t int16; 
    int32_t int32; 
    int64_t int64; 

    uint8_t uint8; 
    uint16_t uint16; 
    uint32_t uint32; 
    uint64_t uint64; 

    scanf("%"SCNd8"%"SCNd16"%"SCNd32"%"SCNd64"%"SCNu8"%"SCNu16"%"SCNu32"%"SCNu64, 
      &int8, &int16, &int32, &int64, &uint8, &uint16, &uint32, &uint64); 

    printf("%"PRId8"\n%"PRId16"\n%"PRId32"\n%"PRId64"\n%"PRIu8"\n%"PRIu16"\n%"PRIu32"\n%"PRIu64"\n", 
      int8, int16, int32, int64, uint8, uint16, uint32, uint64); 

    return 0; 
} 

我無法使用最新的gcc + MinGW + Netbeans + Windows編譯此代碼。 Netbeans說「無法解析標識符SCNd8和SCNu8」。雖然http://linux.die.net/include/inttypes.h定義了它們,但我無法在gcc手冊頁上找到SCNd8和SCNu8的任何參考。我沒有收到使用PRId8或PRIu8的語法錯誤。gcc(windows + MinGW)在inttypes.h中定義了SCNd8,SCNu8嗎?

MinGW的inttypes.h(缺乏SCNd8和SCNu8)(示例代碼)

#define PRIXFAST64 "I64X" 

#define PRIXMAX "I64X" 
#define PRIXPTR "X" 

/* 
* fscanf macros for signed int types 
* NOTE: if 32-bit int is used for int_fast8_t and int_fast16_t 
* (see stdint.h, 7.18.1.3), FAST8 and FAST16 should have 
* no length identifiers 
*/ 

#define SCNd16 "hd" 
#define SCNd32 "d" 
#define SCNd64 "I64d" 

#define SCNdLEAST16 "hd" 
#define SCNdLEAST32 "d" 
#define SCNdLEAST64 "I64d" 

#define SCNdFAST16 "hd"  

回答

3

你可以#include <inttypes.h>後增加以下內容:

#ifndef SCNd8 
    #define SCNd8 "hhd" 
#endif 
#ifndef SCNu8 
    #define SCNu8 "hhu" 
#endif 

這應該是適合大多數平臺。

澄清: 其中「大多數平臺」是指平臺與C99兼容fscanf/scanf可以處理hh前綴char,而不僅僅是h前綴short

+0

是的,你是對的 – gameboy 2010-11-04 23:30:01

+0

@bossgameboy:你使用的是什麼版本的gcc/mingw?在4.5.1中,「hhd」和「hhu」格式不適用於我(即使它們已經在'inttypes.h'中)。 – 2010-11-04 23:53:56

+0

@Michael:「hh」前綴是C99(不是C90)的一部分。檢查您的scanf(或fscanf)版本的手冊頁以確保它與「char」的「hh」兼容。 (C90對於「short」只有「h」)。 – tomlogic 2010-11-10 16:20:15

1

的SCN宏在C99標準,所以事情錯了。也許你需要編譯-std=c99

+0

我沒問題唱任何其他c99功能接受打印長雙值(但這是MinGW + Windows問題)。希望我能知道linux gcc版本是否有這種類型的探針。 – gameboy 2010-11-04 21:29:47

+0

使用C99「long double」可以打印「%Le」,「%Lg」等,我認爲在linux下這個工作沒有問題。你的問題可能不在編譯器本身(gcc)中,而是在你的運行時庫提供的支持中。 – 2010-11-04 21:41:51

+0

是的,在Windows世界中double和long double是一樣的。然而在MINGW中,long double大於double,但是它只能打印MS Windows的長整倍數,也就是雙倍。 – gameboy 2010-11-04 21:46:18

0

那麼......顯然,「最新的gcc + MinGW + Netbeans + Windows」組合不提供兼容的C99編譯器。

標準具體地記錄這些標識符作爲在標題被定義整數類型的<inttypes.h>

7.8格式轉換<inttypes.h>
[...]
7.8.1 [.. ] [#4]簽署整數的fscanf宏:

 SCNdN SCNdLEASTN SCNdFASTN  SCNdMAX SCNdPTR 
     SCNiN SCNiLEASTN SCNiFASTN  SCNiMAX SCNiPTR 

    [#5] The fscanf macros for unsigned integers are: 

     SCNoN SCNoLEASTN SCNoFASTN  SCNoMAX SCNoPTR 
     SCNuN SCNuLEASTN SCNuFASTN  SCNuMAX SCNuPTR 
     SCNxN SCNxLEASTN SCNxFASTN  SCNxMAX SCNxPTR 
+0

是啊,我只是學習C和我爲什麼不使用Visual C++的原因是缺乏C99功能(VC++對C++有好處)。也許我會嘗試使用英特爾C編譯器NetBeans或Visual Studio – gameboy 2010-11-04 21:33:38

4

有趣 - 我有安裝了GCC 4.5.1版的MinGW。

除了輸入8位整數(SCNd8SCNu8)之外,inttypes.h中的格式說明符宏大部分工作。這些宏在inttypes.h中定義,但嘗試使用它們並不能很好地工作。用下面的代碼:

#include <stdio.h> 
#include <inttypes.h> 

int main(void) 
{ 
    int8_t int8 = 0; 
    uint8_t uint8 = 0; 

    scanf("%"SCNd8, &int8); 
    scanf("%"SCNu8, &uint8); 

    return 0; 
} 

我得到以下警告:

C:\temp\test.c: In function 'main': 
C:\temp\test.c:9:5: warning: unknown conversion type character 'h' in format 
C:\temp\test.c:9:5: warning: too many arguments for format 
C:\temp\test.c:10:5: warning: unknown conversion type character 'h' in format 
C:\temp\test.c:10:5: warning: too many arguments for format 

如此看來,GCC 4.5.1和/或glibc的不支持 「%HHD」 和「%HHU 「C99格式說明符。如果我在調試器下運行這個程序,不僅僅是字節變量最終被scanf()調用修改。

僅供參考,我使用下面的命令來編譯:

"C:\MinGW\bin\gcc" -std=c99 -Wall -g -Ic:\MinGW\include -D_WIN32_WINNT=0x0500 "C:\temp\test.c" -lkernel32 -luser32 -lgdi32 -ladvapi32 -lshlwapi -loleaut32 -o "test".exe 

注意,各種字符大小INT輸入格式inttypes.h(即使用「HH」)只能得到,如果編譯C99標準指定了 - 他們的保護:

#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 

其他格式說明中甚至C90編譯編譯。

因此,除非您使用-std=c99-std=gnu99選項(但請記住它們看起來不起作用),否則您將無法獲得「hh」格式。


更新:

當然!不支持「hhd」和「hhu」說明符的原因是因爲MinGW運行時使用來自微軟的msvcrt.dllscanf(),它不知道C99輸入格式中的新東西,如果你想使用這些輸入格式,你需要使用一些其他scanf()實施

正如MinGW的的inttypes.h提到:

MS運行時scanf函數似乎對待 「HH」 爲 「H」

+0

有趣的是,我使用的是MinGW 5.1.6(不知道gcc版本),我查看了MinGW的include文件夾並搜索了inttypes.h頭文件,並且沒有定義SCNd8或SCNu8 ....這裏是從MinGW的樣品inttypes.h – gameboy 2010-11-05 01:43:26

+0

的#define PRIXFAST64 「I64X」 的#define PRIXMAX 「I64X」 的#define PRIXPTR 「X」 /* * 的fscanf宏符號int類型 *注意:如果32位int是用於int_fast8_t和int_fast16_t *(參見stdint.h,7.18.1.3),FAST8和FAST16應具有 *沒有長度標識符 */ 的#define SCNd16 「HD」 的#define SCNd32「d 「 的#define SCNd64 」I64d的「 的#define SCNdLEAST16 」高清「 的#define SCNdLEAST32 」d「 的#define SCNdLEAST64 」I64d的「 的#define SCNdFAST16 」HD「 – gameboy 2010-11-05 01:43:54

+0

@bossgameboy:我使用的是MinGW的包是而不是來自mingw.org(來自http://nuwen.net/mingw.html)。基本組件的版本是:gcc:4.5.1,mingw-runtime:3.18,w32api:3.14。我不知道「MinGW 5.1.6」究竟是指什麼 - 這個數字從哪裏來? – 2010-11-05 18:26:50

1

如果您正在使用MinGW-w64,然後根據MinGW-w64 FAQ,請使用以下定義之前包括

#define __USE_MINGW_ANSI_STDIO 1 

這意味着使用的,而不是推遲對微軟的一個不支持SCNu8的MinGW-W64自己stdio.h實施。無論如何,這是一個好主意,因爲微軟的實施有其他各種重大錯誤。

FAQ中有兩個條目涉及此問題,這裏是the link to the other one


我測試了使用使用gcc (x86_64-posix-sjlj-rev0, Built by MinGW-W64 project) 5.1.0用下面的代碼

#include <inttypes.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main() { 
    uint_fast8_t i = 0; 
    scanf("%" SCNuFAST8 "\n", &i); 
    printf("%" PRIuFAST8 "\n", i); 
    return EXIT_SUCCESS; 
} 

沒有__USE_MINGW_ANSI_STDIO,我

a.c: In function 'main': 
a.c:7:9: error: unknown conversion type character 'h' in format [-Werror=format=] 
    scanf("%" SCNuFAST8 "\n", &i); 
     ^
a.c:7:9: error: too many arguments for format [-Werror=format-extra-args] 

我編譯我的代碼,這樣

>gcc -std=c11 -Wall -Werror a.c 
相關問題