Если сработает второй, это чистая случайность. Тот факт, что это когда-либо работает, доказывает, что, к счастью, компиляторы еще не могут сделать демоны вылетают из твоего носа.
Объявление переменной не обязательно инициализирует ее. В этом случае int n, m;
оставляет как n
, так и m
значения undefined, и попытка доступа к этим значениям является поведением undefined. Если необработанные двоичные данные в памяти, которые указывают на эти точки, случается интерпретироваться в значение, превышающее значения, введенные для n
и m
, что очень и очень далеко от гарантированного, тогда ваш код будет Работа; если нет, то не будет. Ваш компилятор также мог вызвать этот segfault или расплавить ваш процессор; это неопределенное поведение, так что все может случиться.
Например, предположим, что область памяти, которую компилятор выделяет для n
, содержит число 10589231
, а m
получило 14
. Если затем вы введете n
из 12 и m
из 6, вы станете золотым — массив окажется достаточно большим. С другой стороны, если n
получил 4, а m
получил 2, тогда ваш код будет смотреть за конец массива, и вы получите неопределенное поведение, которое может даже не сломаться, поскольку вполне возможно, что биты, хранящиеся в четырехбайтовые сегменты после конца массива доступны как для вашей программы, так и для допустимых целых чисел в соответствии с вашим компилятором/стандартом C. Кроме того, n
и m
могут иметь отрицательные значения, что приводит к... странным вещам. Наверное.
Конечно, все это вздор и предположения, зависящие от компилятора, ОС, времени суток и фазы луны,1, и вы не можете полагаться на то, что какие-либо числа будут инициализированы справа те.
С другой стороны, с первым вы присваиваете значения через scanf
, поэтому (при условии, что это не ошибка) (и введенные числа не являются отрицательными) (или ноль) у вас будут действительные индексы , потому что массив гарантированно будет достаточно большим, потому что переменные инициализированы правильно.
Просто для ясности: хотя при некоторых обстоятельствах переменные должны быть инициализированы нулями, это не означает, что вы должны полагаться на такое поведение. Вы всегда должны явно указывать переменным значение по умолчанию или инициализировать их как можно скорее после их объявления (в случае использования чего-то вроде scanf
). Это делает ваш код более понятным и не дает людям задаваться вопросом, полагаетесь ли вы на этот тип UB.
1: Источник: Райан Бемроуз, в чате
person
Fund Monica's Lawsuit
schedule
07.07.2016
n
иm
не инициализированы.int X[n][m];
использует значения, которыеm
иn
имеют в этой точке кода - вы не можете просто установить их позже, и вы не можете изменить размер массива, изменив их позже. - person Dmitri   schedule 07.07.2016