решение значений мусора по умолчанию в c - PullRequest
2 голосов
/ 11 августа 2010

Если мы объявим переменную в c-программировании как целое число без определения значения, то printf напечатает некоторое значение мусора из буфера.Есть ли какой-нибудь способ предотвратить вывод значения мусора?

Я хочу проверить, можно ли что-то сделать во время компиляции?если возможно?

Ответы [ 5 ]

11 голосов
/ 11 августа 2010

Да. Инициализируйте переменную.

1 голос
/ 04 апреля 2018

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

Однако глобальные переменные могут иметь начальное значение 0, если они помещены в .bss , это оптимизация для уменьшения размера программы.

1 голос
/ 04 апреля 2018

Во время компиляции большинство компиляторов, таких как компилятор GNU, могут определить, где используются неинициализированные переменные. Однако вам может потребоваться установить флаги, такие как -Wall для компилятора GNU.

Здесь значение переменной уже , хотя это может быть любое значение. А именно это «начальное» состояние переменной.

Следовательно, вы должны инициализировать переменную, чтобы избежать мусора.

Когда объявляется переменная x, она уже выделяет раздел для памяти &x, на который ссылается это имя переменной. Неинициализированные значения и переменные уже помещены в адрес памяти. Предположим, вы инициализируете переменную v типа int. Он назначен адресу памяти, который является &v типа int *. Поэтому адрес &v будет помещен в открытое неиспользуемое место в памяти.

Рассмотрим этот код внутри главной функции:

int x; 
// A number of bytes (in this case, sizeof(int), usually 4 B) already allocated
// starting at a memory location &x.

printf("Value at address %p: %d", &x, x); 
// Value at &x may be any int, which is unpredictable

При компиляции этого кода появляется это предупреждение, где SOME_DIRECTORY - произвольный каталог:

SOME_DIRECTORY>gcc -Wall -g sampleprogram.c -o sampleprogram
sampleprogram.c: In function 'main':
sampleprogram.c:8:5: warning: 'x' is used uninitialized in this function [-Wuninitialized]
     printf("Value at address %p: %d", &x, x);

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

1 голос
/ 11 августа 2010

Википедия говорит следующее:

В вычислениях неинициализированная переменная - это переменная, которая объявлена, но не установлена ​​на определенное известное значение перед ее использованием.Это будет иметь некоторое значение, но не предсказуемое.Как таковая, это ошибка программирования и общий источник ошибок в программном обеспечении

Так что инициализируйте его значением по умолчанию.

0 голосов
/ 04 апреля 2018

Вы, безусловно, хотите скомпилировать все предупреждения и информацию отладки: gcc -Wall -Wextra -g с GCC . Тогда вполне вероятно, что вы получите предупреждения, и вы должны улучшить свой код, чтобы не получать ни одного.

Конечно, вы должны инициализировать свои переменные . Кстати, такая инициализация коротка для кода и выполняется очень быстро. И в нескольких случаях (например, -O1) gcc может оптимизировать (используя правило как-будто ) и удалить бесполезные инициализации. Так что, как правило, не бойтесь «бесполезных» инициализаций.

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

Подробнее о неопределенное поведение . Будьте напуганы UB.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...