Gcc (windows + MinGW) определяет SCNd8, SCNu8 в inttypes.h? - PullRequest
5 голосов
/ 05 ноября 2010
#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». Я не могу найти ссылки для SCNd8 и SCNu8 на странице руководства gcc, хотя http://linux.die.net/include/inttypes.h определяет их. Я не получаю синтаксическую ошибку при использовании PRId8 или PRIu8.

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"    

Ответы [ 5 ]

4 голосов
/ 05 ноября 2010

Интересно - у меня MinGW с установленной GCC версии 4.5.1.

Макросы спецификатора формата в inttypes.h работают по большей части, за исключением тех, которые для ввода 8-битных целых (* 1004)* и SCNu8).Эти макросы определены в 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.Если я запускаю эту программу в отладчике, меняются не только байтовые переменные do при вызовах 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 размером с символ (в которых используется "hh") в inttypes.h компилируются, только если указан стандарт C99 - они защищены:

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

Другие спецификаторы формата скомпилированы даже для компиляций C90.

Таким образом, вы не получите форматы "hh", если не будете использовать опции -std=c99 или -std=gnu99(но помните, что они все равно не работают).


Обновление:

Конечно!Причина, по которой спецификаторы "hhd" и "hhu" не поддерживаются, заключается в том, что среда выполнения MinGW использует scanf() из msvcrt.dll от Microsoft, который ничего не знает о новом материале во входных форматах C99. Если вы хотите использоватьэти входные форматы, вам нужно будет использовать некоторые другие реализации scanf().

Как уже упоминалось в inttypes.h MinGW:

MSf runf scanf, по-видимому, обрабатывает "чч" как"ч"

4 голосов
/ 05 ноября 2010

Вы можете добавить следующее после #include <inttypes.h>:

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

Что должно подходить для большинства платформ.

Пояснение: Где «большинство платформ» относится к платформам с C99-совместимым fscanf / scanf, которые могут обрабатывать префикс hh для char, а не только префикс h для short.

1 голос
/ 08 августа 2015

Если вы используете MinGW-w64, то в соответствии с MinGW-w64 FAQ , используйте следующее определение, прежде чем включить

#define __USE_MINGW_ANSI_STDIO 1

Это означает использование собственной реализации stdio.h в MinGW-w64 вместо того, чтобы откладывать реализацию Microsoft, которая не поддерживает SCNu8. В любом случае, это хорошая идея, поскольку в реализации Microsoft есть и другие серьезные ошибки.

В FAQ есть две записи о проблеме, вот ссылка на другую .


Я проверил это, используя 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
1 голос
/ 05 ноября 2010

Макросы SCN соответствуют стандарту C99, поэтому что-то идет не так.Возможно, вам придется скомпилировать с -std=c99.

0 голосов
/ 05 ноября 2010

Ну ... очевидно, комбинация "последние версии gcc + MinGW + Netbeans + Windows" не обеспечивает совместимый компилятор C99.

Стандарт специально документирует эти идентификаторы, как они определены в заголовке <inttypes.h>

7.8 Преобразование формата целых типов
[...]
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
...