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

Это самоназвание делает что-то разумное?

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

char * acFilename = acFilename;

EDIT: компилятор жалуется на предупреждение C4700, что я использую неинициализированную переменную.

4b9b3361

Ответ 1

В области блоков в С++ это поведение undefined, так как правая часть считывает переменную в переменной перед ее инициализацией (C + +14 [dcl.init]/12).

В области блоков в C11 это может быть либо undefined поведение, либо вести себя как неинициализированная переменная, в зависимости от различных деталей реализации и остальной функции, см. здесь для подробного анализа.

В области пространства имен, в С++, это OK четко определено и делает нулевой указатель. Это связано с тем, что все статические переменные инициализируются нулем до того, как будут рассмотрены их инициализаторы. (С++ 14 [basic.start.init]/2).

В области файлов в C это нарушение ограничения; статические переменные должны иметь постоянное выражение как инициализатор, а значение переменной не может быть постоянным выражением.

Ответ 2

Этот код не имеет никакого смысла. Вероятно, это опечатка, возможно, кто-то хотел использовать

char* acFilename = ::acFilename;

или

char* acFilename = m_acFilename;

или что-то еще.

Как бы то ни было, это сбивает с толку и бесполезно в лучшем случае, вероятно, ошибка, потому что кто-то хотел использовать другую переменную.

Ответ 3

Я видел это раньше. Поскольку gcc довольно запутанный, с его неинициализированными переменными предупреждениями, это трюк, чтобы заставить замолчать эти предупреждения. Не уверен, что намеренный выбор дизайна gcc или компилятор просто глупый, но я видел, как люди делают это специально, чтобы заставить gcc заткнуться (и в этом случае нарушить предупреждение, которое может быть правильным в будущем).

Я бы просто заменил его инициализацией на NULL. Это плохая привычка, не работает на других компиляторах, и NULL не может быть менее корректным, чем неопределенное значение и поведение undefined.

Просто, чтобы продемонстрировать, как это работает (а также потому, что я хотел знать, продолжают ли это делать новые версии gcc):

$ cat foo.c
int
foobar(void)
{
    int foo;
    return foo + foo;
}
$ cc -c -Wall -O2 foo.c
foo.c: In function ‘foobar’:
foo.c:6:13: warning: ‘foo’ is used uninitialized in this function [-Wuninitialized]
  return foo + foo;
         ~~~~^~~~~
$ ed foo.c
[...]
$ cc -c -Wall -O2 foo.c
$ cat foo.c
int
foobar(void)
{
    int foo = foo;
    return foo + foo;
}
$ cc -c -Wall -O2 foo.c
$ cc -v
[...]
gcc version 6.2.0 20161005 (Ubuntu 6.2.0-5ubuntu12)
$

Ответ 4

В некоторых местах внутри программы может быть возможно, чтобы переменная находилась в одном из следующих условий:

  • Входы, которые были получены, заставили переменную записать, а также заставят код использовать ее значение в будущем.

  • Входы, которые были получены, заставили переменную не записываться, но также могут привести к тому, что код не будет использовать ее значение.

Некоторые компиляторы скручиваются, если видят, что существуют входы, которые заставляют переменную не писать, и есть входы, которые заставили бы эту переменную читать. Даже если единственный вход, который заставит переменную читать, также заставит ее писать, компиляторы могут этого не осознавать. Хотя можно было бы отключить жалобы компилятора, безоговорочно инициализируя переменную, машинный код, который инициализирует переменную значением, которое никогда не может использоваться, не будет служить функциональной цели. Конструкция исходного кода, которая бы заглушала жалобы компилятора, но не приводила к компилятору, генерирующему бесполезный машинный код, может быть предпочтительнее того, который должен был бы генерировать бесполезный машинный код. В некоторых компиляторах может быть использована самоинициализирующая декларация.

Если у типа есть ловушечные представления, нет никакой практической альтернативы написанию инициализации, что компилятор, скорее всего, превратится в бесполезный машинный код, но если у типа нет ловушных представлений, нет никакой особой причины, почему качественный компилятор должен заставить программистов запросить бесполезный код, который им не нужен и не нужен. Однако, вместо того, чтобы пытаться иметь разные правила для платформ, где существуют различные типы и не имеют ловушечных представлений, авторы Стандарта отдают суждениям разработчиков о том, какое поведение будет разумным для конкретной целевой платформы и приложения поле.

Если на какой-либо платформе компилятор не мог позволить программистам опустить инициализацию для переменных, которые копируются, но в противном случае не используются без необходимости генерации вероятных избыточных инициализаций, было бы разумно потребовать, чтобы программист включил инициализации во всех ситуациях, которые может произойти. На другой платформе, где копирование бессмысленного значения просто приведет к тому, что место назначения будет иметь бессмысленное значение, однако, как правило, имеет смысл дать возможность программисту опустить инициализацию в случаях, когда ни одна из копий никогда не будет использована для любых реальных цель. Авторы Стандарта не прилагают никаких усилий, чтобы указать, что будет иметь смысл в любом конкретном случае, потому что они ожидают, что люди, пишущие реализации, должны быть способны проявлять здравый смысл.

Лучший подход для решения этой ситуации, вероятно, заключался бы в том, чтобы написать макрос, который принимает переменную, и чье расширение будет инициализировать переменную до нуля (для реализаций, авторы которых считают, что есть больше значений, позволяющих компиляторам перескакивать рельсы, когда копируется неинициализированная переменная, даже если ни одна из копий действительно не используется для чего-либо, чем было бы гарантировано, что простой акт копирования переменной не будет иметь побочных эффектов) или ничего не делать (при использовании реализация, которая останется на рельсах, даже без бесполезной инициализации).