Что это значит? int foo = foo + 4;
#include <iostream>
int main(int argc, char** args) {
int foo = foo + 4;
std::cout << foo << std::endl;
}
И следующий вопрос: есть ли флаг компилятора, чтобы остановить подобное? Я обнаружил, что -Word работает иногда, лучше было бы предотвратить это полностью.
My compiler:
g++ -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)
Ответы
Ответ 1
Нет никакого гарантированного способа остановить подобное. Это неотъемлемая часть С++ и C, что имя переменной видно в ее инициализаторе. Это позволяет делать такие вещи, как
T *t = malloc(sizeof(*t));
В списке проблем С++ есть отчет о проблеме, требующий диагностики в простых случаях, но в настоящее время компиляторы не обязаны диагностировать ваш случай.
Он также действителен в другом контексте.
Изменить: уточнить - поведение вашего фрагмента undefined: вы читаете значение не инициализированной переменной. Эти компиляторы не обязаны диагностировать это не означает, что поведение определено.
Ответ 2
int foo = foo + 4;
Это поведение undefined. Некоторые компиляторы автоматически обнуляют пространство для локальных переменных, если другие не могут, поэтому foo может содержать стек мусора
Ответ 3
Я могу поспорить, что это означает поведение undefined.
Изменить: см. цитату из ответ на другой вопрос.
Изменить: скорее всего, значение в RHS берется из неинициализированной ячейки памяти в стеке, к ней добавляется 4, и результат используется для инициализации.
Ответ 4
Чтобы получить предупреждение от gcc для этого конкретного кода, вам нужно -Wuninitialized
(-Wall
включает это) и -O
(или любой уровень оптимизации выше 0).
Причина заключается в том, что gcc не может диагностировать использование неинициализированных переменных, если не анализирует поток данных, и при оптимизации оптимизации не выполняется анализ потока данных. По умолчанию оптимизация отключена.
Ответ 5
Я бы ожидал, что какой-нибудь полуподобный достойный компилятор выдает предупреждение для int foo = foo + 4; в своей конфигурации по умолчанию. У хороших есть варианты отклонить его полностью как "использование неинициализированной переменной" и/или принять какое-либо конкретное происхождение, когда программист точно понимает, что происходит и не беспокоится о неожиданном поведении.
Я, например, часто использовал для записи int toggle = toggle ^ 1 в те дни, когда компиляторы не были такими суетливыми, если бы все, что я хотел, было переключателем переключения, где мне было все равно, он начал ИСТИННО или ЛОЖЬ. В настоящее время я бы, вероятно, написал статический bool toggle = TRUE; переключение = ^ тумблер