Как решить значения мусора по умолчанию в C?

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

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


person mielacademy    schedule 11.08.2010    source источник


Ответы (5)


да. Инициализировать переменную.

person PaulJWilliams    schedule 11.08.2010
comment
Я бы использовал только опцию компилятора intilization (для разных значений, например, 0, 1, 0xFF) для целей тестирования. - person Peter G.; 11.08.2010
comment
@mielacademy: всегда передавайте хотя бы -O -Wall в gcc, тогда он будет предупреждать о типичных ошибках, таких как неинициализированные переменные. См. Также stackoverflow.com/questions/3375697/useful-gcc -flags-for-c - person Gilles 'SO- stop being evil'; 11.08.2010
comment
Вы не должны использовать параметры компилятора, чтобы обойти ошибку в вашей студентке. И не заблуждайтесь, использование неинициализированной переменной является ошибкой. - person PaulJWilliams; 11.08.2010
comment
Чертова опечатка. У меня, кстати, однажды была ошибка в моей студентке, но пенициллин с этим справился. - person PaulJWilliams; 11.08.2010

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

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

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

person Praveen S    schedule 11.08.2010

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

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

person GH0S1    schedule 04.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 не устанавливает никаких требований, поэтому может случиться что угодно. Это очень серьезная ошибка, которая может вызвать множество трудно отслеживаемых ошибок и сбоев.

person Ṃųỻịgǻňạcểơửṩ    schedule 04.04.2018

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

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

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

Подробнее о неопределенном поведении. Будьте бояться UB.

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

person Basile Starynkevitch    schedule 04.04.2018