GCC で「非推奨の文字列定数から char* への変換」の警告を取り除くにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/59670

  •  09-06-2019
  •  | 
  •  

質問

そこで、私は非常に大規模なコードベースに取り組んでおり、最近 gcc 4.3 にアップグレードしたところ、次の警告がトリガーされるようになりました。

警告:文字列定数から「char*」への非推奨の変換

明らかに、これを修正する正しい方法は、次のような宣言をすべて見つけることです。

char *s = "constant string";

または次のような関数呼び出し:

void foo(char *s);
foo("constant string");

そしてそれらを作ります const char ポインタ。ただし、これは少なくとも 564 個のファイルを操作することを意味し、現時点で実行したいタスクではありません。今の問題は、私が実行していることです -werror, したがって、これらの警告を抑制する何らかの方法が必要です。どうやってやるの?

役に立ちましたか?

解決

合格すると信じています -Wno-write-strings gcc に設定すると、この警告が抑制されます。

他のヒント

文字列リテラルを渡す関数 "I am a string literal" 使用する必要があります char const * 代わりにタイプとして char*.

何かを修正する場合は、正しく修正してください。

説明:

文字列リテラルを使用して、変更される文字列を初期化することはできません。 const char*. 。後で変更するために定数をキャストすることは、 未定義の動作, 、したがって、あなたのものをコピーする必要があります const char* 文字列 char による char 動的に割り当てられる char* 文字列を変更するためのものです。

例:

#include <iostream>

void print(char* ch);

void print(const char* ch) {
    std::cout<<ch;
}

int main() {
    print("Hello");
    return 0;
}

gcc をチェックしてください 診断プラグマ サポート、およびリスト -W 警告オプション (かわった: 警告オプションへの新しいリンク).

gcc の場合は、次を使用できます #pragma warning 説明したようなディレクティブ ここ.

私も同様の問題を抱えていましたが、次のように解決しました。

#include <string.h>

extern void foo(char* m);

int main() {
    // warning: deprecated conversion from string constant to ‘char*’
    //foo("Hello");

    // no more warning
    char msg[] = "Hello";
    foo(msg);
}

これはこれを解決する適切な方法でしょうか?にアクセスできません foo 受け入れられるように調整する const char*, 、それはより良い解決策ではありますが(なぜなら foo 変わらない m).

アクティブなコード ベースの場合でも、コード ベースをアップグレードする必要がある場合があります。もちろん、手動で変更を実行するのは現実的ではありませんが、この問題は 1 回で完全に解決できると信じています。 sed 指示。ただし、私は試したことがないので、以下の内容は話半分に聞いてください。

find . -exec sed -E -i .backup -n \
    -e 's/char\s*\*\s*(\w+)\s*= "/char const* \1 = "/g' {} \;

これにより、すべての場所が見つからない可能性があります (関数呼び出しを考慮していない場合でも) が、問題が軽減され、残りのいくつかの変更を手動で実行できるようになります。

コンパイラスイッチが使えない。それで私はこれを変えました:

char *setf = tigetstr("setf");

これに:

char *setf = tigetstr((char *)"setf");

Makefile を変更する必要がないように、ファイル内でインラインで実行する方法を次に示します。

// gets rid of annoying "deprecated conversion from string constant blah blah" warning
#pragma GCC diagnostic ignored "-Wwrite-strings"

後でできます...

#pragma GCC diagnostic pop

交換する

char *str = "hello";

char *str = (char*)"hello";

または関数内で呼び出している場合:

foo("hello");

これを次のように置き換えます

foo((char*) "hello");

の代わりに:

void foo(char *s);
foo("constant string");

これは機能します:

void foo(const char s[]);
foo("constant string");

C++ では、 const_cast 以下のように

char* str = const_cast<char*>("Test string");

Test string 定数文字列です。したがって、次のように解決できます。

char str[] = "Test string";

または:

const char* str = "Test string";
printf(str);

なぜ型キャストを使用しないのでしょうか?

(char*) "test"

定数文字列からcharポインタへの型キャストを実行します。つまり、

char *s = (char *) "constant string";

C++ では、次のように置き換えます。

char *str = "hello";

と:

std::string str ("hello");

そして、それを比較したい場合は、次のようにします。

str.compare("HALLO");

あなたのソリューションを適用する方法がわかりません:( – kalmanIsAGameChanger

Arduino Sketch を使用していると、警告を引き起こす関数がありました。

オリジナル機能:char StrContains(char *str, char *sfind)

警告を停止するには、 定数 char *str と char *sfind の前。

変更:char StrContains(const char *str, const char *sfind)。

すべての警告が消えました。

この状況を見てください:

typedef struct tagPyTypeObject
{
    PyObject_HEAD;
    char *name;
    PrintFun print;
    AddFun add;
    HashFun hash;
} PyTypeObject;

PyTypeObject PyDict_Type=
{
    PyObject_HEAD_INIT(&PyType_Type),
    "dict",
    dict_print,
    0,
    0
};

name フィールドに注目してください。gcc では警告なしでコンパイルされますが、g++ ではコンパイルされます。理由はわかりません。

を呼び出して、文字列定数から書き込み可能な文字列を作成することもできます。 strdup().

たとえば、次のコードは警告を生成します。

putenv("DEBUG=1");

ただし、次のコードはそうではありません (文字列をヒープに渡す前に、文字列のコピーをヒープ上に作成します)。 putenv):

putenv(strdup("DEBUG=1"));

この場合 (そしておそらく他のほとんどの場合でも) 警告をオフにするのは悪い考えです。これには理由があります。もう 1 つの方法 (デフォルトですべての文字列を書き込み可能にする) は、非効率である可能性があります。

コンパイラの言うことを聞いてください。

g++ には -w オプションを使用してください

例:

g++ -w -o simple.o simple.cpp -lpthread

これは非推奨を回避するものではなく、端末に警告メッセージが表示されないようにするものであることに注意してください。

本当に非推奨を避けたい場合は、次のように const キーワードを使用します。

const char* s="constant string";  

を使用しないのはなぜですか -Wno-deprecated 非推奨の警告メッセージを無視するオプションはありますか?

現在の問題は、-Werror を使用して実行していることです

これがあなたの本当の問題です、IMO。(char *) から (const char *) に移行する自動化された方法をいくつか試すこともできますが、私は単に機能するだけではなく、それらにお金をかけたいと思います。少なくとも一部の作業には人間が関与する必要があります。短期的には、この警告を無視して (ただし、IMO は警告をオンのままにしなければ、修正されることはありません)、-Werror を削除するだけです。

皆さん、助けてくれてありがとう。あちこちから選んでこの解決策が得られます。これはクリーンにコンパイルされます。まだコードをテストしていません。明日...多分...

const char * timeServer[] = { "pool.ntp.org" }; // 0 - Worldwide 
#define WHICH_NTP            0 // Which NTP server name to use.
...
sendNTPpacket(const_cast<char*>(timeServer[WHICH_NTP])); // send an NTP packet to a server
...
void sendNTPpacket(char* address) { code }

timeServer 配列には項目が 1 つしかありません。しかし、それ以上の可能性もあります。メモリを節約するために、残りの部分は今のところコメントアウトされています。

BlackShift の答えは非常に役に立ちます。私はそれを次のように使用しました。

extern string execute(char* cmd) {
            FILE* pipe = popen(cmd, "r");
            if (!pipe) return "ERROR";
            char buffer[256];
            std::string result = " ";
            while(!feof(pipe)) {
                    if(fgets(buffer, 128, pipe) != NULL)
                            result += buffer;
            }
            pclose(pipe);
            return result;
    }
    int main(){
            char cmd[]="grep -A1 'xml' out1.txt  | grep read|awk -F'=' 'BEGIN{sum=0}{sum=sum+$NF}END{print sum}'";
            string result=execute(cmd);
            int numOfBytes= atoi(result.c_str());   
            cout<<"Number of bytes = "<<numOfBytes<<endl;
            return 0;
    }
PyTypeObject PyDict_Type=
{ ...

PyTypeObject PyDict_Type=
{
  PyObject_HEAD_INIT(&PyType_Type),
                     "dict",
                     dict_print,
                     0,
                     0
}; 

name フィールドに注目してください。gcc では警告なしでコンパイルされますが、g++ ではコンパイルされます。理由はわかりません。

gcc (Compiling C), -Wno-write-strings はデフォルトでアクティブです。

g++ (Compiling C++) -Wwrite-strings はデフォルトでアクティブです

このため、異なる動作が発生します。のマクロを使用する私たちにとって、 Boost_python このような警告を生成します。そこで私たちは使用します -Wno-write-strings C++ をコンパイルするときは常に使用するため、 -Werror

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top