【问题标题】:Printing GetWindowTextA is wrong when printing outside function打印外部函数时打印 GetWindowTextA 错误
【发布时间】:2022-01-30 01:10:42
【问题描述】:

我是 C++ 的新手,来自 C# 背景,如果这是一个愚蠢的问题,请原谅我。

我有以下通过句柄获取窗口标题的函数。

char* GetWindowTitle(HWND hwnd) {
    char winTitle[56];
    GetWindowTextA(hwnd, winTitle, sizeof(winTitle));
    printf("Title: %s\n", winTitle);

    return winTitle;
}

该函数中的printf正确输出Title: a.txt - Notepad

但是如果我对函数的返回做同样的事情:

printf("Title: %s\n", GetWindowTitle(hwnd));

现在的输出是“标题:`÷S”

是什么导致了这种不同的行为?

【问题讨论】:

    标签: c++ winapi char printf


    【解决方案1】:

    您正在返回函数本地的地址。它仅在该函数的持续时间内存在。

    char* GetWindowTitle(HWND hwnd) {
        char winTitle[56];  <====== this is destroyed when the function ends
        GetWindowTextA(hwnd, winTitle, sizeof(winTitle));
        printf("Title: %s\n", winTitle);
    
        return winTitle;
    }
    

    试试这个:

    #include <string>
    
    std::string GetWindowTitle(HWND hwnd) {
        char winTitle[56];
        GetWindowTextA(hwnd, winTitle, sizeof(winTitle));
        printf("Title: %s\n", winTitle);
    
        return std::string(winTitle);
    }
    

    这将在堆上分配一个std::string。一旦你不再在调用代码中引用它,它就会被删除。

    要使用printf() 显示此字符串,请执行以下操作:

    printf("Title: %s\n", GetWindowTitle(hwnd).c_str());
    

    不过,您应该改掉使用 C 风格 I/O(printf() 等)的习惯。要使用 C++ 风格的 I/O 显示此字符串,请执行以下操作:

    #include <iostream>
    
    std::cout << "Title: " << GetWindowTitle(hwnd) << std::endl;
    

    如果你打算写大量的C++代码,学会使用:

    • std::string(C# 中的string
    • std::shared_ptrstd::unique_ptr(C# 中的类对象引用)
    • std::vector(C# 中的List
    • std::map(C# 中的Dictionary

    【讨论】:

    • "这将在堆上分配一个std::string" - 这是一种误导。 std::string 本身不在堆上,但它的有效负载可能在。使用 SSO(短字符串优化),它可能根本不在堆上。
    • @RemyLebeau 我知道,但我不想详细介绍。说它像 c# 中的字符串一样工作(我是 C# 和 C++ 开发人员)向 OP 传达了正确的动态。
    • C# 中的string 等价于C++ 中的std::wstring“改掉使用 C 风格 I/O 的习惯” - 的确如此。虽然替换不应该是 C++ 的 I/O 流。 C++20 引入了formatting library,它结合了printf 的简洁格式化DSL 和I/O 流的类型安全。而且它比 I/O 流快很多。此外,这里的一个关键要点应该是:不要忽视警告。 /WX 编译器选项非常有效。
    • @IInspectable 他使用的是 ascii 而不是宽字符。这将涉及比 OP 需要的更多信息。我讨厌 cout
    • “他正在使用 ascii” - 不,他没有。他正在调用 ANSI API。 ANSI 使用环境字符集,它可能是也可能不是预期的字符集。这通常是不可取的。但这真的不是重点:C# 中的 string 存储 UTF-16 编码的文本。另一方面,C++ 中的std::string 用于存储任何内容,ASCII、ANSI、UTF-8 等,但不是 UTF-16。这就是std::wstring(或std::u16string)的用途。
    猜你喜欢
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-07
    • 2019-05-01
    • 2020-02-11
    相关资源
    最近更新 更多