2010-11-04 33 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; 
} 

Je ne peux pas compiler ce code en utilisant la dernière version de gcc + MinGW + Netbeans + Windows. Netbeans dit "incapable de résoudre l'identifiant SCNd8 et SCNu8". Je ne trouve aucune référence pour SCNd8 et SCNu8 sur la page de manuel gcc bien que http://linux.die.net/include/inttypes.h les définit. Je ne reçois pas d'erreur de syntaxe pour l'utilisation de PRId8 ou PRIu8.Est-ce que gcc (windows + MinGW) définit SCNd8, SCNu8 dans inttypes.h?

MinGW inttypes.h (manque SCNd8 et SCNu8) (code exemple)

#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"  

Répondre

3

Vous pouvez ajouter ce qui suit après #include <inttypes.h>:

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

qui devrait convenir à la plupart des plates-formes.

Précision: où « la plupart des plates-formes » fait référence à des plates-formes avec une C99 conforme fscanf/scanf qui peut gérer le préfixe hh pour char, non seulement le préfixe h pour short.

+0

oui, vous avez raison – gameboy

+0

@bossgameboy: Quelle version de gcc/mingw utilisez-vous? les formats "hhd" et "hhu" ne fonctionnent pas pour moi avec 4.5.1 (même s'ils sont déjà dans 'inttypes.h'). –

+0

@Michael: le préfixe "hh" fait partie de C99 (pas C90). Vérifiez la page de manuel pour votre version de scanf (ou fscanf) pour vous assurer qu'elle est compatible avec "hh" pour 'char'. (C90 a juste "h" pour "court"). – tomlogic

1

Les macros SCN sont dans la norme C99, donc quelque chose va mal. Peut-être que vous auriez à compiler avec -std=c99.

+0

Je n'ai aucun problème chanter n'importe quelle autre fonctionnalité c99 accepte l'impression double valeur longue (mais c'est problème MinGW + Windows). Je voudrais pouvoir savoir que la version Linux gcc a ce genre de problème. – gameboy

+0

Avec C99 'long double' peut être imprimé avec"% Le ","% Lg "etc et je pense que sous Linux cela fonctionne sans problèmes. Votre problème n'est probablement pas dans le compilateur lui-même (gcc) mais dans le support que votre bibliothèque d'exécution offre. –

+0

Oui, Dans le monde de Windows double et long double est le même. Cependant, dans MINGW long double est plus grand que double, mais il ne peut imprimer que le double long de MS Windows, c'est le double. – gameboy

0

Bien ... apparemment la combinaison "dernier gcc + MinGW + Netbeans + Windows" ne fournit pas un compilateur C99 conforme.

La norme documente spécifiquement les identifiants comme étant définis dans l'en-tête <inttypes.h>

7,8 Conversion de format des types entiers <inttypes.h>
[...]
7.8.1 [.. .] [4] Les macros fscanf pour les entiers signés sont:

 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

ouais, je suis en train d'apprendre c et la raison pour laquelle je n'utilise pas Visual C++ est l'absence de fonctionnalités c99 (VC++ est bon pour C++). Peut-être que je vais essayer NetBeans ou Visual Studio avec Intel C Compiler – gameboy

4

Intéressant - J'ai MinGW avec la version 4.5.1 de GCC installée.

Les macros de spécification de format dans inttypes.h fonctionnent pour la plupart, à l'exception de celles pour l'entrée des entrées de 8 bits (SCNd8 et SCNu8). Ces macros sont définies dans inttypes.h, mais essayer de les utiliser ne fonctionne pas très bien. Avec le code suivant:

#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; 
} 

Je reçois les avertissements suivants:

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 

Il semble donc que GCC 4.5.1 et/ou glibc ne prennent pas en charge le "% HHD" et « % TSP "Les spécificateurs de format C99. Si je cours ce programme sous un débogueur, plus que juste les variables d'octet font finissent par être modifiés par les scanf() appels.

Juste pour référence, j'utilise la commande suivante pour compiler:

"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 

Notez que les différents formats d'entrée int taille de caractères (que l'utilisation « hh ») dans inttypes.h ne se compilés si la norme C99 est spécifiée - ils sont protégés par:

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

Les autres spécificateurs de format sont compilés en même C90 compile. Donc, vous n'obtiendrez pas les formats "hh" à moins d'utiliser les options -std=c99 ou -std=gnu99 (mais rappelez-vous qu'ils ne semblent pas fonctionner de toute façon).


Mise à jour:

Bien sûr! La raison pour laquelle les spécificateurs "hhd" et "hhu" ne sont pas supportés est que le runtime MinGW utilise le scanf() de Microsoft msvcrt.dll qui ne sait rien sur les nouvelles choses dans les formats d'entrée de C99. Si vous voulez utiliser ces formats d'entrée, vous aurez besoin d'utiliser une autre implémentation scanf()

comme mentionné dans inttypes.h de MinGW.

MS exécution de scanf semble traiter "hh" comme "h"

+0

intéressant, j'utilise MinGW 5.1.6 (je ne sais pas quelle version de gcc), j'ai regardé inclure le dossier de MinGW et recherché inttypes.h en-tête et il n'y a pas de définitions pour SCNd8 ou SCNu8 .... voici la échantillon de MinGW inttypes.h – gameboy

+0

#define PRIXFAST64 "I64X" #define PRIXMAX "I64X" #define PRIXPTR "X" /* * fscanf macros pour les types int signé * REMARQUE: si int 32 bits est utilisé pour int_fast8_t et int_fast16_t * (voir stdint.h, 7.18.1.3), FAST8 et FAST16 devraient avoir * aucun identificateur de longueur */ #define SCNd16 "HD" #define SCNd32 « d " #define SCNd64 "I64d" #define SCNdLEAST16 "hd" #define SCNdLEAST32 "d" #define SCNdLEAST64 "I64d" #define SCNdFAST16 "hd" – gameboy

+0

@bossgameboy: J'utilise un paquet MinGW qui est pas de mingw.org (c'est de http://nuwen.net/mingw.html). Les versions des composants essentiels sont: gcc: 4.5.1, mingw-runtime: 3.18, w32api: 3.14. Je ne sais pas à quoi se réfère exactement "MinGW 5.1.6" - d'où vient ce nombre? –

1

Si vous utilisez MinGW-w64, puis selon le MinGW-w64 FAQ, utilisez les touches suivantes définissent avant comprend

#define __USE_MINGW_ANSI_STDIO 1 

Cela signifie utiliser propre implémentation stdio.h de MinGW-w64, au lieu de reporter à celui de Microsoft qui ne supporte pas SCNu8. C'est une bonne idée de toute façon car l'implémentation de Microsoft a plusieurs autres bugs majeurs.

Il y a deux entrées dans la FAQ concernant le problème, voici the link to the other one.


J'ai testé à l'aide en utilisant ce gcc (x86_64-posix-sjlj-rev0, Built by MinGW-W64 project) 5.1.0 avec le code suivant

#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; 
} 

Sans __USE_MINGW_ANSI_STDIO, je me suis

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] 

Je compile mon code comme ceci

>gcc -std=c11 -Wall -Werror a.c