多次元配列の空の文字列リテラルがnullポインターに減衰するのはなぜですか?


8

いくつかの文字列リテラルで初期化された多次元C文字列配列を定義したいと思います。ではC Iは、次の操作を行います:

#include <stdio.h>

const char *strArr[2][1] = { {"foo"}, {""}};

int main(void) {
    printf("%p\t%p\n", strArr[0][0], strArr[1][0]);
    return 0;
}

gcc -std=c18 -pedantic test.c結果をコンパイルして実行すると、次のようになります。

$ ./a.out 
0x55d95410f004  0x55d95410f008

予想どおり、空の文字列リテラルはstrArr[1][0]有効なポインタに減衰します。


しかし、私は同じコードを試してみてくださいC ++

#include <cstdio>

const char *strArr[2][1] = { {"foo"}, {""}};

int main(void) {
    printf("%p\t%p\n", strArr[0][0], strArr[1][0]);
    return 0;
}

g++ -std=c++17 -pedantic test.cpp結果をコンパイルして実行すると、次のようになります。

$ ./a.out 
0x55c61494d004  (nil)

ここでは、空の文字列リテラルはstrArr[1][0]nullポインターに減衰します。これはなぜC ++で起こるのですか?


C ++ 17標準では、5.13.5の段落16に次のように表示されます。

通常の文字列リテラルおよびUTF-8文字列リテラルは、ナロー文字列リテラルとも呼ばれます。ナロー文字列リテラルのタイプは「n const charの配列」で、nは以下で定義する文字列のサイズで、静的な保存期間(6.7)を持っています。

これは、空の文字列リテラルが通常の文字列リテラルであるため、静的な保存期間が必要であることを示しているようです。では、なぜ空の文字列リテラルがnullポインタに減衰するのでしょうか。


1
そもそもなぜCスタイルの配列を使うのですか?なんでstd::array
Jesper Juhl、

2
@super空の文字列には、ターミネーターという1つの文字があります。印刷すると、何も出力されません。
Weather Vane

3
これはおそらくGCC 9の退行です。あなたはそれを報告し、彼らが言うことを見るべきです。
ブライアン、

2
g ++はこれを行いますが、clangは行いません:gcc.godbolt.org/z/XkZcVy g ++バグのように見えます。
PSkocik

1
GCC bugzillaサイトでの@KeithThompsonアカウントの作成は制限されているので、明日までに完了すると期待されるメールリクエストを送信しました。今のところ、Gentooのバグレポートを開いています
Vilhelm Grey

回答:



0

そのような腐敗はありません。観察した出力はコンパイラのバグです。

(はい、これは短い答えですが、他に追加することはありません)。


質問へのコメントから、それはGentooで報告されたg ++ 9の回帰です:bugs.gentoo.org/701364
キース・トンプソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.