Странные значения при инициализации массива

Я новичок в программировании на C, и я нашел что-то, чего не понимаю:

При инициализации массива без заданных значений я думал, что все элементы будут равны нулю. Я написал несколько строк кода ...

int main()                    
{     
    int obj[10][4];

    for (int a = 0; a < 10; a++)
    {
        print("%d\t%d\t%d\t%d\n", obj[a][0], obj[a][1], obj[a][2], obj[a][3]);
    }            
}

... и был довольно смущен его выходом:

0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       7661
7960    2697    2260    7960
1551630361      -2130960380     146780176       -2130960380

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

int main()                    
{     
    int obj[10][4];

    print("start\tstop\tcenter\tdist\n\n");

    for (int a = 0; a < 10; a++)
    {
        print("%d\t%d\t%d\t%d\n", obj[a][0], obj[a][1], obj[a][2], obj[a][3]);
    }            
}

... получение этого:

start   stop    center  dist

0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       0
0       0       0       7673
7972    2709    2272    7972
1551630361      -2130960380     146780176       -2130960380

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

Я нашел решение здесь, в SO , используя memset() , это работает для меня, но ... что здесь происходит?

Может кто-нибудь объяснить это, используя слова, которые C-новичок поймет?

2
Ну, вы не инициализировали, поэтому получаете неинициализированные значения. В основном нули, но никогда не гарантируется.
добавлено автор stefan, источник
Совет для дальнейшего развития: если вы получаете поведение неожиданное с действительно странными значениями, попробуйте выполнить valgrind . Это может дать вам подсказки, где ошибка (неинициализированные переменные довольно хорошо обнаруживаются valgrind).
добавлено автор stefan, источник
Да, я знаю, что это очень в начале, поверьте мне, я знаю новичков ;-) Но всегда полезно знать, что искать. Два шага: добавьте -g к вашему вызову компилятора (вы, вероятно, сейчас набираете gcc -Wall -std = c99 my_file.c -o my_binary , поэтому это становится gcc -g -Wall -std = c99 my_file.c -o my_binary ). Второй шаг: вместо этого выполните следующие действия: ./ my_binary , вы выполните valgrind ./my_binary . Вот и все. Если есть «... неинициализированное значение ...», там также указан файл и строка, и вы можете изучить проблему. Просто попробуйте с кодом вашего вопроса!
добавлено автор stefan, источник
Ах я вижу. Ну, это делает обучение немного сложнее, на мой взгляд ;-)
добавлено автор stefan, источник
@stefan: Спасибо за эту информацию, но сейчас это слишком много. Я искал valgrind и добавил закладки в некоторые сайты, которые я мог бы понять после использования C немного дольше ;-)
добавлено автор xph, источник
@stefan: Ну, дело в том, что ... я не кодирую «обычный» способ. Я пишу на C для небольшой платы Propeller, используя IDE, построенную именно для этого маленького компьютера. Я даже не использую обычный компилятор, это все-встроенное решение, чтобы получить некоторый код на доске самым удобным способом, aka «Нажмите эту кнопку, когда закончите» . Если я собираюсь придерживаться этого, я бы посмотрел на него глубже. Возможно, я могу использовать инструменты my для программирования этого компьютера, и тогда это будет очень удобно!
добавлено автор xph, источник
Да, согласился. Он не собирается преподавать некоторое «правильное» использование C, но для меня это не совсем так. Эта плата предназначена для создания и изучения робототехники , и я в основном сосредоточен на датчиках, сервосистемах и так далее. Конечно, код необходим, чтобы все было сделано. По крайней мере, причина «связаться» с C, языком, которого я всегда избегал до сих пор. Но среда IDE ... не очень хорошая. Если я ищу новые приключения, я постараюсь избавиться от него.
добавлено автор xph, источник

7 ответы

Simply put, you can not assume the array is initialized to 0 unless you explicitly made the initialization yourself. The C standard does not guarantee anything about the content of the array, just that you'll have memory allocated for it.
A great reference on initializing and arrays in C general can be found here:http://www.tutorialspoint.com/cprogramming/c_multi_dimensional_arrays.htm

4
добавлено
... так что я сделал это неправильно. Спасибо за объяснение и ссылку!
добавлено автор xph, источник

У вас есть объявление переменной, но нет инициализации.

Если вы хотите, чтобы ваш массив был инициализирован нолем, просто поставьте это:

int obj[10][4] = {0};
2
добавлено
Спасибо! Теперь я знаю ошибку, которую я сделал - только если значения some определены, остальное будет равно нулю. Сделай это!
добавлено автор xph, источник

класс класса хранения int obj [10] [4] - это auto , и он хранится в стеке. auto не получают инициализированные значения, т. е. имеют значения мусора. Если вы хотите, чтобы массив инициализировался нулями, сделайте его глобальным, то есть объявите массив вне функции main() ,

1
добавлено

Начальные значения ничего не определены. Ваш код просто определяет массив - он никогда не присваивает никакого значения тому, что в нем.

1
добавлено
@xph Да, именно там вы ошибаетесь. Неинициализация означает значения мусора.
добавлено автор stefan, источник
Да, но примеры, которые я встретил, показывают, что «no value» означает «zero, then». Получил ли я это неправильно и «нет значения» просто означает «что угодно» ..?
добавлено автор xph, источник
@stefan: Получил! :-)
добавлено автор xph, источник

стек содержит мусор, пока программа не поместит определенные значения в переменные, определенные в стеке. Код запуска не инициализирует содержимое стека.

Примечание: переменные глобального глобального пространства/файла инициализируются кодом запуска. где не указан какой-либо конкретный инициализатор, тогда память устанавливается на 0x00.

0
добавлено

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

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

0
добавлено

Не эксперт, а гипотеза из опыта:

Если вы инициализируете массив как static int myArray [1000] , тогда C выделяет новую память, заполненную 1000 нулями на время работы программы. Инициализация с помощью int myArray [1000] просто ограничивает 1000 регистров, некоторые из которых могут содержать старые значения из предыдущего использования регистра.

0
добавлено