为什么 wprintf() 函数不给我 TEXT 宏的输出?

问题描述 投票:0回答:1

我正在尝试按如下方式编译 WinApi 应用程序,但我没有得到输出 -

#include <windows.h>
#define UNICODE 

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{

  wprintf(TEXT("%s"), TEXT("Hello")) ;

}

我还有 GCC 的输出 -

app.c: In function 'WinMain':
app.c:9:3: warning: implicit declaration of function 'wprintf'; did you mean 'wsprintf'? [-Wimplicit-function-declaration]
    9 |   wprintf(TEXT("%s"), TEXT("Hello")) ;
      |   ^~~~~~~
      |   wsprintf

但是,如果我按照以下方式重写函数,我会得到正确的输出,但编译器会出现相同的警告 -

#include <windows.h>
#define UNICODE 

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
  
  wprintf(L"%s", L"Hello") ; 

}

我正在使用

GCC 13.2.0 from MSYS32
并编译此应用程序,没有任何标志,如下所示:
gcc app.c -o app

  • 为什么第一个变体没有输出,而第二个变体却有?语句
    wprintf(TEXT("%s"), TEXT("Hello")) ;
    不会扩展为
    wprintf(L"%s", L"Hello") ; 
    吗?
  • 这个编译器警告是什么意思?
c winapi
1个回答
0
投票

我们先来说第二个问题:

这个编译器警告是什么意思?

警告指出您正在使用 C 编程语言的一项功能,该功能非常危险,以至于在 C99 中它被提升为错误:每当编译器看到带有它不知道的函数名称的函数调用表达式时,它都会继续执行并发明声明。以下示例可以编译,尽管它不应该编译。

不幸的是,链接器以某种方式发现了

wprintf()
符号并生成了一个它不应该有的二进制文件。更糟糕的是,GCC 默认不实现 C99,所以通过
-std=c99
也救不了你。

解决方案很简单:要拨打

wprintf()
,您必须
#include <wchar.h>
。这引入了
wprintf()
的声明,以便编译器可以生成正确的函数调用代码。


第一个问题需要更多文字来解释。主要收获是:

不要使用通用文本映射

它们的引入是为了帮助开发人员从 Win9x 过渡到基于 WinNT 的系统,方法是提供一个粗略的转换层来解释不同的默认字符编码(Win9x 的 ANSI 代码页编码和 WinNT 的 UCS-2/UTF-16)。

为什么第一个变体没有输出,而第二个变体有输出?

它们并不等同。第一段代码构造了narrow字符串文字。使用

TEXT()
宏没有任何作用。具体问题在这里:

#include <windows.h>
#define UNICODE 

这指示编译器处理来自 标头及其传递依赖项的所有预处理器指令,并且 then 定义

UNICODE
预处理器符号。这样做不会追溯改变
TEXT()
的含义:它仍然只是一个空操作。

这就引出了你没有问的第三个问题:

为什么这还能编译?

这是C编程语言的另一个特点:指针只是指针。事实上,您可以将类型与指针对象关联起来,这一事实会让编译器“不为所动”(模警告)。它要求一个指针,它得到一个指针,就是这样。 更改顺序将使两个程序相同。但这仍然是错误的,即使无关紧要。

再次强调,
您不应该使用通用文本映射

,但如果您必须使用,至少不要弄错。默认情况下“犯错”,让我们快速了解一下规则:

通用文本映射通过预处理器符号
    UNICODE
  • _UNICODE
    MBCS
    _MBCS
    进行控制。始终在编译器命令行上传递它们,例如
    -D _UNICODE
    预处理器符号控制两个独立的区域:Win32 API 表面 (
  • UNICODE
  • /
    MBCS
    ) 和 C 运行时 (
    _UNICODE
    /
    _MBCS
    )。
    TEXT 与 _TEXT 与 _T,以及 UNICODE 与 _UNICODE
    更详细地解释了这一点。 字符串文字必须包含在
  • TEXT()
  • _TEXT()
    /
    _T()
    宏中。根据功能所属区域选择正确的宏,例如 CRT 为
    _TEXT()
    始终调用函数的通用文本映射。 CRT 的(非标准)扩展带有 
  • _t
  • 前缀,例如
    _tprintf()
    。对于 Win32 API,通用文本映射没有
    A
    W
    后缀。
    
    
  • 这将是使用通用文本映射的正确实现:

#include <windows.h> #include <wchar.h> int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { _tprintf(_TEXT("%s"), _TEXT("Hello")) ; }

如果您不使用通用文本映射,您可能会忘记在这里阅读的所有内容。这样做你不会失去任何东西。

© www.soinside.com 2019 - 2024. All rights reserved.