【问题标题】:C program shows %zu after conversion to WindowsC程序转换为Windows后显示%zu
【发布时间】:2017-10-29 20:16:36
【问题描述】:

我通过 Mingw 在 Windows 上编译了一个 linux 程序。但是,程序的输出在 Windows 上看起来与在 Linux 上不同。

例如,在 Windows 上,输出是这样的(我得到的是 'zu' 而不是实数):

Approximated minimal memory consumption:
Sequence        : zuM
Buffer          : 1 X zuM = zuM
Table           : 1 X zuM = zuM
Miscellaneous   : zuM
Total           : zuM

在 Linux 上,原始程序编译(没有 Mingw)时会出现警告。在 Windows 上,在 Mingw 下,它以零警告编译。

有什么需要注意的吗?
Mingw 是否提供 100% 的兼容性,或者我必须修改程序才能在 Win 上运行?

我不知道该往哪个方向走。我应该从哪里开始尝试修复程序?
你认为我使用 Cygwin 有更好的机会吗?


更新:
维基百科提到这一点:“缺乏对 C99 的支持导致了移植问题,特别是在涉及 printf 样式转换说明符的情况下”。
这就是我撞到头的东西吗?

更新:
我的mingw版本是:

MINGWBASEDIR=C:\MinGW
gcc version 4.8.1 (GCC)
gcc version 4.8.1 (GCC)
GNU gdb (GDB) 7.6.1
GNU ld (GNU Binutils) 2.24
GNU windres (GNU Binutils) 2.24
GNU dlltool (GNU Binutils) 2.24
GNU Make 3.82.90
#define __MINGW32_VERSION           3.20
#define __W32API_VERSION 3.17

(我使用此代码获取版本:

@echo off
REM version-of-mingw.bat
REM credit to Peter Ward work in ReactOS Build Environment RosBE.cmd it gave me a starting point that I edited.
::
:: Display the current version of GCC, ld, make and others.
::

REM %CD% works in Windows XP, not sure when it was added to Windows
REM set MINGWBASEDIR=C:\MinGW
set MINGWBASEDIR=%CD%
ECHO MINGWBASEDIR=%MINGWBASEDIR%
SET PATH=%MINGWBASEDIR%\bin;%SystemRoot%\system32
if exist %MINGWBASEDIR%\bin\gcc.exe (gcc -v 2>&1 | find "gcc version")
REM if exist %MINGWBASEDIR%\bin\gcc.exe gcc -print-search-dirs
if exist %MINGWBASEDIR%\bin\c++.exe (c++ -v 2>&1 | find "gcc version")
if exist %MINGWBASEDIR%\bin\gcc-sjlj.exe (gcc-sjlj.exe -v 2>&1 | find "gcc version")
if exist %MINGWBASEDIR%\bin\gcc-dw2.exe (gcc-dw2.exe -v 2>&1 | find "gcc version")
if exist %MINGWBASEDIR%\bin\gdb.exe (gdb.exe -v | find "GNU gdb")
if exist %MINGWBASEDIR%\bin\nasm.exe (nasm -v)
if exist %MINGWBASEDIR%\bin\ld.exe (ld -v)
if exist %MINGWBASEDIR%\bin\windres.exe (windres --version | find "GNU windres")
if exist %MINGWBASEDIR%\bin\dlltool.exe (dlltool --version | find "GNU dlltool")
if exist %MINGWBASEDIR%\bin\pexports.exe (pexports | find "PExports" )
if exist %MINGWBASEDIR%\bin\mingw32-make.exe (mingw32-make -v | find "GNU Make")
if exist %MINGWBASEDIR%\bin\make.exe (ECHO It is not recommended to have make.exe in mingw/bin)
REM ECHO "The minGW runtime version is the same as __MINGW32_VERSION"
if exist "%MINGWBASEDIR%\include\_mingw.h" (type "%MINGWBASEDIR%\include\_mingw.h" | find "__MINGW32_VERSION" | find "#define")
if exist "%MINGWBASEDIR%\include\w32api.h" (type "%MINGWBASEDIR%\include\w32api.h" | find "__W32API_VERSION")

:_end
PAUSE

)

【问题讨论】:

  • 如果您需要更多信息,请告诉我。
  • %zu 应该是 size_t 的可移植 printf 格式说明符,等等。它是在 C99 中添加的。您使用的是最近的 MinGW 吗?
  • MinGW 绝对不假装与 Linux 兼容。它是用于构建 Windows 应用程序的 Windows 编译器。 (它也不假装与其他 Windows 编译器兼容,但这是另一个问题)。在这种情况下,您的问题很可能正如 knarf 所暗示的那样,MinGW 运行时(恰好与 Micrsoft 的运行时相同)不支持 %zu。 Cygwin 可能会更好,但我不知道它是否支持这种特殊情况。它使用与 MinGW 和 Linux 不同的 C 运行时库。
  • @knarf-我发布了关于我的 Mingw 的详细信息
  • 该错误报告确实为您的问题提出了解决方案:“在包含stdio.h 之前将USE_MINGW_ANSI_STDIO 定义为1

标签: linux windows g++ cygwin mingw


【解决方案1】:

正如bug report discussion linked in the comments 所建议的,Microsoft 的printf 函数不支持C99。如果宏 __USE_MINGW_ANSI_STDIO 在包含任何标题之前或在命令行上设置为 1,则 mingw-w64 项目提供的替代函数可以像普通 C99 函数一样使用。它们支持标准的%zu%jd 等格式说明符,即使是最新的 MSVCRT 版本也不支持。您可以直接使用mingw_printf调用该函数,但通常更容易将上述宏定义为1并调用printf等。

值得注意的是,如果你使用微软的snprintf,如果缓冲区不够大,它会返回-1表示截断,除非缓冲区和缓冲区大小参数分别为NULL和0,这种情况下返回将输出的字节数。 C99 的行为是,如果缓冲区足够大,则始终返回将输出的字节数,或者如果发生编码错误,则返回负值,并且 mingw-w64 实现似乎根据 C99 表现正确。

如果您使用任何printf 函数,您需要做的就是在任何包含之前使用#define __USE_MINGW_ANSI_STDIO 1,或者只需将-D__USE_MINGW_ANSI_STDIO=1 添加到您的编译器调用中。

如果您担心宏会干扰其他平台,那么除了提供类似功能的原始(旧版?)MinGW[32] 项目之外,没有其他实现实际上应该使用此预处理器宏,因此定义它是安全的无条件的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多