こんにちは。
最近、Windows10の上でVisualStudio2019を使用してC言語のプログラミングをしていると気になったことができたので質問させていただきました。
気になったことというのは「文字列リテラル」についてです。
普段、自分はUbuntuの上でgccを用いてプログラミングしているのですが、いつもは文字列リテラルのアドレスを持つポインタを初期化する際、次のようなコードを書いていました。(gcc -dumpversionで調べると、gccのバージョンは7でした)
このコードはgccでは問題なくコンパイルされました。
しかし、これをVisualStudioでためしてみると次のようなエラーが出ます。
僕は文字列リテラルは読み込み専用領域に配置されると学んだので(環境によっては違うのかもしれませんが...)VisualStudioの対応が正しいと思うのですが、gccによると問題ないみたいです。
gccの側で文字列リテラルの中身を書き換えようとした場合はしっかりsegmentation faultがでます。
つまり、文字列リテラルはconst charの配列ということですよね?
これはgccの手抜き(??)という認識で正しいのでしょうか?
どなたか知識をお貸しください。
【C言語】文字列リテラルのデータ型について
Re: 【C言語】文字列リテラルのデータ型について
まず、これは C言語ではなく C++ ではないですか?
C言語でこのエラーはでないはずです。
歴史的経緯もあって以前の規格 (C++98/C++03) では、char * を文字列リテラルで初期化するのは許容されていました。C++11 以降の規格では禁止されました。Visual Studio (VC) でもオプションなしではエラーになりません。
Visual Studio でプロジェクトを作成するとデフォルトで /permissive- オプションが設定され、エラーになります。
/permissive- オプションなしにすると過去のバージョンとの互換性を重視して、規格に厳密に準拠しなくなります。
gcc でもオプションによってはエラーあるいは警告が出ます。-Werror=write-strings オプションを指定するとエラーになり、-Wwrite-strings オプションでは警告が出ます。
vc や gcc でデフォルトでエラーにしない理由はよく判りませんが、過去に作られたソースを修正なしにコンパイルするためかもしれません。
いずれにしても文字列リテラルは書き換え禁止なので const char * が正しいです。過去のソースはともかく新規に作成されるソースは const char * にすべきですね。
C言語でこのエラーはでないはずです。
歴史的経緯もあって以前の規格 (C++98/C++03) では、char * を文字列リテラルで初期化するのは許容されていました。C++11 以降の規格では禁止されました。Visual Studio (VC) でもオプションなしではエラーになりません。
Visual Studio でプロジェクトを作成するとデフォルトで /permissive- オプションが設定され、エラーになります。
/permissive- オプションなしにすると過去のバージョンとの互換性を重視して、規格に厳密に準拠しなくなります。
gcc でもオプションによってはエラーあるいは警告が出ます。-Werror=write-strings オプションを指定するとエラーになり、-Wwrite-strings オプションでは警告が出ます。
vc や gcc でデフォルトでエラーにしない理由はよく判りませんが、過去に作られたソースを修正なしにコンパイルするためかもしれません。
いずれにしても文字列リテラルは書き換え禁止なので const char * が正しいです。過去のソースはともかく新規に作成されるソースは const char * にすべきですね。