EDIT:
Я прошу прощения за то, что предположил, что это будет очевидно, но "не забывайте игнорировать предупреждения" не следует воспринимать всерьез. На самом деле, я думаю, что это будет единственной причиной переписать программу.
Скомпилируйте следующую программу (не забывайте игнорировать предупреждения!) :
#include <stdio.h>
int main ()
{
long int i;
long int j;
scanf("%d", &i);
scanf("%ld", &j);
printf("i == %ld\n", i);
printf("j == %ld\n", j);
return 0;
}
Запустите ее и введите целое число больше, чем 2147483647 двараз, и вы получите свои ответы.
СПОЙЛЕР:
Я сделал это с 4294967297, и было напечатано следующее:
i == 1
j == 4294967297
Конечно,Ответ зависит от архитектуры, и я предположил, что ваша машина хранит int
в 32 битах. Но если есть причина использовать long int
для хранения в нем числа, лучше использовать модификатор длины (если это не имеет значения, вам не нужно использовать long int
).
Но чтобы ответить на ваши вопросы немного более явно:
Означает ли это, что модификатор длины изменяет тип назначенной переменной, если он на самом деле не соответствует значению формата, определенного с помощьюспецификатор преобразования?
Нет. Как вы видели, когда пытаетесь сохранить значение, которое должно вписаться в long int
без модификатора длины, вы будете действовать так, как если бы вы сохраняли в int
(даже если бы происходило переполнение). Если вы используете %ld
с scanf
, чтобы попытаться сохранить значение в переменной int
, то не будет выброшено segfault, и это может привести к плохим вещам. Компиляция следующего (и необходимость игнорировать предупреждение ради эксперимента):
#include <stdio.h>
int main ()
{
int k[2] = {0,0};
printf("k[0] == %d\n", k[0]);
printf("k[1] == %d\n", k[1]);
scanf("%ld", &k);
printf("k[0] == %d\n", k[0]);
printf("k[1] == %d\n", k[1]);
return 0;
}
и запуск его путем ввода 4294968300 распечаток:
k[0] == 0
k[1] == 0
4294968300
k[0] == 1004
k[1] == 1
означает, что пресловутый scanf
записал прошлое k[0]
в k[1]
совершенно незамеченным!
Почему я [sic] должен точно применять модификатор длины в операторе, независимо от того, объявил ли я [sic] присваивающую переменную как, например, long int, правильную или нет?
Я совершенно не понимаю, почему я [sic] должен это делать, и не вижу никакой разницы в выводе между включением его и выполнением без модификатора длины.
Я думаю, что примеры вышедолжен дать вам сильный стимул не игнорировать предупреждения при попытке компиляции с модификатором несоответствующей длины в вызове scanf
. В противном случае вы можете даже столкнуться с угрозой безопасности.