簡體   English   中英

C ++不推薦將字符串常量轉換為'char *'

[英]C++ deprecated conversion from string constant to 'char*'

我有一個private char str[256];的類private char str[256];

為此,我有一個顯式的構造函數:

explicit myClass(const char *func)
{
    strcpy(str,func);
}

我稱之為:

myClass obj("example");

當我編譯這個時,我得到以下警告:

不推薦將字符串常量轉換為'char *'

為什么會這樣?

警告:

不推薦將字符串常量轉換為'char *'

是因為你在某處(不是在你發布的代碼中)做的事情是這樣的:

void foo(char* str);
foo("hello");

問題是您正在嘗試將字符串文字(類型為const char[] )轉換為char*

你可以將const char[]轉換為const char*因為數組衰減到指針,但你正在做的是使一個可變的常量。

這種轉換可能允許C兼容性,只是給你提到的警告。

這是您遇到以下情況時看到的錯誤消息:

char* pointer_to_nonconst = "string literal";

為什么? 那么,C和C ++在字符串文字的類型上有所不同。 在C中,類型是char數組,在C ++中,它是char的常量數組。 在任何情況下,都不允許更改字符串文字的字符,因此C ++中的const實際上不是限制,而是更多類型安全的東西。 出於安全原因,如果沒有顯式強制轉換,通常無法從const char*轉換為char* 但是為了向后兼容C,語言C ++仍然允許將字符串文字分配給char*並提供有關不推薦使用此轉換的警告。

所以,在某個地方,你在程序中缺少一個或多個const來保持const的正確性。 但是,您向我們展示的代碼不是問題,因為它不會執行此類不推薦的轉換。 警告必須來自其他地方。

作為答案否。 2由fnieto - Fernando Nieto清楚而正確地描述了這個警告是因為你正在做的代碼中的某個地方(不是你發布的代碼中):

void foo(char* str);
foo("hello");

但是,如果您希望保持代碼無警告,則只需對代碼進行相應更改:

void foo(char* str);
foo((char *)"hello");

也就是說,簡單地將string常量強制轉換為(char *)

有3種解決方案:

解決方案1:

const char *x = "foo bar";

解決方案2:

char *x = (char *)"foo bar";

解決方案3:

char* x = (char*) malloc(strlen("foo bar")+1); // +1 for the terminator
strcpy(x,"foo bar");

也可以使用數組代替指針,因為數組已經是常量指針。

事實上,字符串常量文字既不是const char *也不是char *而是char []。 它很奇怪,但在c ++規范中寫下來; 如果修改它,則行為未定義,因為編譯器可能將其存儲在代碼段中。

也許你可以試試這個:

void foo(const char* str) 
{
    // Do something
}

foo("Hello")

這個對我有用

我通過在代碼的開頭添加這個宏來解決這個問題。 或者在<iostream>添加它,呵呵。

 #define C_TEXT( text ) ((char*)std::string( text ).c_str())

我也遇到了同樣的問題。 我簡單的做法就是添加const char *而不是char *。 問題解決了。 正如其他人在上面提到的,這是一個兼容的錯誤。 C將字符串視為char數組,而C ++將它們視為const char數組。

為了它的價值,我發現這個簡單的包裝類有助於將C ++字符串轉換為char *

class StringWrapper {
    std::vector<char> vec;
public:
    StringWrapper(const std::string &str) : vec(str.begin(), str.end()) {
    }

    char *getChars() {
        return &vec[0];
    }
};

這個問題的原因(比使用char* str = "some string"的問題更難以檢測到 - 其他人已經解釋過)就是當你使用constexpr

constexpr char* str = "some string";

看起來它的行為類似於const char* str ,因此它不會引發警告,因為它發生在char*之前,但它反過來表現為char* const str

細節

常量指針和指向常量的指針。 const char* strchar* const str之間的區別可以解釋如下。

  1. const char* str :聲明str是指向const char的指針。 這意味着該指針指向它的數據是常量。 指針可以被修改,但任何修改數據的嘗試都會引發編譯錯誤。
    1. str++ ; 有效 我們正在修改指針,而不是指向的數據。
    2. *str = 'a'; 無效 我們正在嘗試修改指向的數據。
  2. char* const str :聲明str是一個指向char的const指針。 這意味着點現在是常量,但指向的數據也不是。 指針無法修改,但我們可以使用指針修改數據。
    1. str++ ; 無效 我們正在嘗試修改指針變量,這是一個常量。
    2. *str = 'a'; 有效 我們正在嘗試修改指向的數據。 在我們的例子中,這不會導致編譯錯誤,但會導致運行時錯誤 ,因為字符串很可能會進入已編譯二進制文件的只讀部分。 如果我們有動態分配的內存,這個陳述是有意義的,例如。 char* const str = new char[5];
  3. const char* const str :聲明str是一個指向const char的const指針。 在這種情況下,我們既不能修改指針,也不能修改指向的數據。
    1. str++ ; 無效 我們正在嘗試修改指針變量,這是一個常量。
    2. *str = 'a'; 無效 我們正在嘗試修改此指針指向的數據,該指針也是常量。

在我的情況下,問題是我期望constexpr char* str表現為const char* str ,而不是char* const str ,因為從視覺上看它似乎更接近前者。

另外,對於所產生的警告constexpr char* str = "some string"是從稍微不同char* str = "some string"

  1. constexpr char* str = "some string"編譯器警告: ISO C++11 does not allow conversion from string literal to 'char *const'
  2. char* str = "some string"編譯器警告: ISO C++11 does not allow conversion from string literal to 'char *'

小費

您可以使用C gibberish↔英語轉換器C聲明轉換為易於理解的英語語句,反之亦然。 這是一個僅限C工具,因此不支持C++獨有的東西(如constexpr)。

下面說明了解決方案,將字符串分配給指向常量char數組的變量指針(字符串是指向常量char數組的常量指針 - 加上長度信息):

#include <iostream>

void Swap(const char * & left, const char * & right) {
    const char *const temp = left;
    left = right;
    right = temp;
}

int main() {
    const char * x = "Hello"; // These works because you are making a variable
    const char * y = "World"; // pointer to a constant string
    std::cout << "x = " << x << ", y = " << y << '\n';
    Swap(x, y);
    std::cout << "x = " << x << ", y = " << y << '\n';
}

暫無
暫無

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

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