GCC で「非推奨の文字列定数から char* への変換」の警告を取り除くにはどうすればよいですか?
質問
そこで、私は非常に大規模なコードベースに取り組んでおり、最近 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