Подтвердить что ты не робот

Самый неприятный синтаксический анализ с доступом к массиву

При взгляде на некоторый код С++ 03 я нашел экземпляр наиболее неприятного разбора, который смутил меня:

#include <sstream>
#include <string>

int main(int, char** argv)
{
    std::stringstream ss(std::string(argv[0]));
}

живой пример в wandbox

В приведенном выше фрагменте ss является объявлением функции, которая принимает std::string* и возвращает std::stringstream.

Как std::string(argv[0]) анализируется как std::string*?

Интуитивно я думал, что argv[0] был однозначно доступ к argv.

4b9b3361

Ответ 1

Причина в том, что в контексте объявления функции компилятор интерпретирует std::string(argv[0]) как std::string argv[0], то есть объявление массива нулевого размера как параметр функции с именем argv (затеняет argv от main, так как это другая область), которая затем эквивалентна указателю с помощью распада массива-указателя.

Следовательно, std::stringstream ss(std::string(argv[0])); означает то же самое, что std::stringstream ss(std::string* argv);

Изменить: поскольку он был правильно аннотирован в комментариях, объявления массива нулевого размера недействительны в С++, что делает программу плохо сформированной. При компиляции этого кода с флагами -pedantic (GCC и clang) будут выданы предупреждения. Visual Studio даже создает ошибку компиляции. Для любого другого индекса массива, кроме 0, аргумент выше, тем не менее, сохраняется.

Ответ 2

Я считаю, что это следует из принципа синтаксиса "синтаксис объявления как принцип синтаксиса выражения", и тот факт, что параметры "массива" являются указателями.

Следующие объявления массива эквивалентны:

int x[1];
int (x)[1];
int (x[1]);

более или менее, потому что x[a], (x)[a] и (x[a]) являются эквивалентными выражениями.

Таким образом,

std::stringstream ss(std::string(argv[0]))

                 <=>

std::stringstream ss(std::string argv[0])

                 <=>

std::stringstream ss(std::string* argv)