簡體   English   中英

為什么將字符串傳遞給接受 LPSTR 的 function 不起作用?

[英]why passing string to a function which accepts LPSTR does noy work?

以下代碼給出了空字符串和長度 = 0,但在調試時我可以看到 childDisplayName 具有正確的名稱。

    CHAR fileSystemName[MAX_PATH + 1] = { 0 }; 
    DWORD serialNumber = 0; DWORD maxComponentLen = 0; 
    string childDisplayName = "";
    DWORD fileSystemFlags = 0; 
    if (GetVolumeInformationA("C:\\", // L"\\MyServer\MyShare\"
        (LPSTR)&childDisplayName, MAX_PATH+1,
        &serialNumber, &maxComponentLen,
        &fileSystemFlags, fileSystemName, sizeof(fileSystemName)) == true)
    {
        
        cout << childDisplayName << "length: "<<childDisplayName.length()<<endl;
    }


以下代碼工作正常。 我不明白為什么 LPSTR 在傳遞 char 數組時有效,而在傳遞字符串時卻無效。

    CHAR fileSystemName[MAX_PATH + 1] = { 0 }; 
    DWORD serialNumber = 0; DWORD maxComponentLen = 0; 
    CHAR childDisplayName[MAX_PATH + 1] = { 0 };
    DWORD fileSystemFlags = 0; 
    if (GetVolumeInformationA("C:\\", // L"\\MyServer\MyShare\"
        childDisplayName, MAX_PATH+1,
        &serialNumber, &maxComponentLen,
        &fileSystemFlags, fileSystemName, sizeof(fileSystemName)) == true)
    {
        
        cout << childDisplayName << "length: "<<strlen(childDisplayName)<<endl;
    }

string childDisplayName = ""; 創建一個空的空字符串(零大小和未指定的容量)。 使用它作為數據緩沖區寫入不太可能 go 很好。

你可以這樣做: string childDisplayName(MAX_PATH + 1, ' '); 創建一個分配了適當空間的字符串。

其次,正如@churill 所寫,字符串的地址不是其中字符的地址。 而是使用childDisplayName.data()char*獲取到您可以寫入的字符串的內部存儲 - 但請確保不要寫入范圍[data(); data() + size()) [data(); data() + size())

編輯:關於std::string.data()的工作原理。

我做了一個小示例程序:

#include<iostream>
#include<string>

void print(const std::string& s)
{
    std::cout << "String size: " << s.size() << '\n';
    std::cout << "String contents: >>" << s << "<<\n";
    std::cout << "String as c-string: >>" << s.c_str() << "<<\n";
    std::cout << '\n';
}

int main() {
    std::string bla = "";
    auto bladata = bla.data();
    for (int i = 0;i < 5;++i) {
        bladata[i] = '!';
    }
    print(bla);

    std::string bla2(10, '\0');
    auto bla2data = bla2.data();
    for (int i = 0;i < 5;++i) {
        bla2data[i] = '!';
    }
    print(bla2);
}

運行此輸出時:

String size: 0
String contents: >><<
String as c-string: >>!!!!!╠╠╠╠╠╠╠╠╠╠╠<<

String size: 10
String contents: >>!!!!!     <<
String as c-string: >>!!!!!<<

這里發生了什么? 首先要注意的是,一個空的std::string是用零大小和未指定的容量創建的 - 在我的調試器中查看,我知道在我的系統上未指定的容量是 15,所以只要我不 go 之外什么都沒有應該崩潰。 但這顯然不是您在實際代碼中應該做的事情(在這里編寫是嚴格未定義的行為)。

這意味着bla字符串的大小為 0,包含一個 15 個字符的字符緩沖區,我將前 5 個字符設置為“.”。 因此,當我嘗試打印它的size()或將其打印為std::string時,它與任何常規的空字符串相同。 但是,如果我使用.c_str()直接打印內部緩沖區,那么它將打印為任何舊的char*並且只打印 memory 中的任何內容,直到遇到空字符。

另一方面, bla2被初始化為包含 10 個空字符。 這意味着它的大小是 10,它的容量至少是 10(在我的例子中它恰好也是 15)。 這意味着在循環之后它仍然報告大小為 10,無論我將多少個 ',' 放入緩沖區,當我將其打印為std::string時,它會打印它包含的所有 10 個字符; 5 '.' 和 5 '\0',但是,當我將其打印為char*時,它會打印 5 '.',然后在遇到空字符時立即停止。

在第一個代碼片段中,我無法獲得 childDisplayName 的正確名稱。

在此處輸入圖像描述

雖然它看起來有幾個字符,但是當我想 output 時觸發了異常。

在此處輸入圖像描述

因此,您將錯誤的地址傳遞給GetVolumeInformationA 。因為字符串的地址不是字符的地址

您可以像下面的代碼一樣進行測試:

string s("test");
CHAR cs[] = "test";
cout << (void*)&s << endl;
cout << (void*)&s[0] << endl;

cout << (void*)&cs << endl;
cout << (void*)&cs[0] << endl;

Output: 在此處輸入圖像描述

正如@churill 所說, std::string只管理一個動態的字符數組。所以你不能將字符串的地址傳遞給 function。

根據MSDN

如果修改數據的 const 重載返回的字符串的內容,則行為未定義。 如果終端 null 字符更改為任何其他值,您也會得到未定義的行為。 如果對字符串的非常量引用傳遞給標准庫 function,則返回的指針可能會失效。 它也可以通過調用非常量成員 function 來使其無效。

所以即使你真的成功地將childDisplayName.data()傳遞到 function 中。 這也是一種未定義的行為。我建議您正確傳遞function所需的參數類型,而不是嘗試傳遞其他未定義或無類型的行為,這會給您帶來很多困惑。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM