предупреждение: формат "% d" ожидает тип "int *", но аргумент 2 имеет тип "int" - PullRequest
8 голосов
/ 20 января 2011

Итак, я новичок в C и у меня проблемы с тем, что происходит с этим предупреждением. Что означает предупреждение и как я могу это исправить. Код, который я написал здесь:

void main(void)
{
  char* name = "";
  int age = 0;
  printf("input your name\n");
  scanf("%s\n", name);
  printf("input your age\n");
  scanf("%d\n", age);
  printf("%s %d\n", name, age);

}

Ответы [ 7 ]

12 голосов
/ 20 января 2011

Функция scanf принимает адрес переменной, чтобы поместить результат в.
Запись scanf("%d", <b><i>&</i></b>someVar) передаст адрес переменной someVar (используя унарный оператор &).
Функция scanf поместит число в часть памяти по этому адресу.(которая содержит вашу переменную)

Когда вы пишете scanf("%d", age), вы передаете значение переменной age в scanf.Он попытается вставить число в часть памяти по адресу 0 (так как age равно 0) и ужасно запутается.

Вам нужно передать &age в scanf.

Вам также нужно выделить память для scanf для чтения строки в name:

char name[100];
scanf("%99s\n", name);
6 голосов
/ 20 января 2011

Проблема в следующей строке:

scanf("%d\n", age);

scanf ожидает аргументы указателя - это единственный способ, которым функции могут изменять параметры в C. Чтобы исправить это, вам необходимо:

scanf("%d\n", &age);

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

Что касается этого:

char* name = "";

Ой-ой-пожалуйста-не!Хорошо, мне нужно объяснить.Вы просили указатель на тип символа, но для всех, все, что у вас есть, это символ, а не целая строка.Это верно, не хватает места.Почему C позволяет вам это сделать?Ну, C в основном переносимый ассемблер, так что вы можете писать где угодно в памяти (точнее, вы можете попробовать, и компилятор не согласится, но операционная система может и, вероятно, будет).

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

Это может, хотя и неозначает, приведет к уязвимости на основе стека.Что, стеки? Да.Стек - это структура FILO, и каждый раз, когда вы вызываете функцию, вы добавляете пространство в стек для своего адреса возврата и аргументов функции, а также часто переменных области действия функции.

Где это становится проблемой, еслиВы не проверяете входные размеры.Затем я могу записать огромные значения в ваш стек, включая исполняемый код ... см. Переполнение буфера .

Итак, как мне это смягчить, как я слышал, вы говорите, просто жаждя не реализовыватьпрограммные уязвимости?Вы используете функции, которые позволяют вам указать размер входного буфера и считывать данные в буфер определенного размера, и переходите оттуда.Вот и все.Это просто.

См. Этот вопрос: чтение строки в C .

1 голос
/ 20 января 2011

Вы должны написать scanf("%d", &age), так как функция scanf должна изменить значение age, поэтому необходимо передавать его "по адресу", а не "по значению".

0 голосов
/ 20 января 2011
char* name = "";

name указывает на бит или объем памяти, достаточный для хранения одного нулевого символа.

scanf("%s\n", name);

Вы запрашиваете неизвестное количество символов для чтения и сохранения по этому адресу. Может произойти все, что угодно .Вы должны убедиться, что name имеет адрес части памяти, достаточно большой, чтобы вместить все, что scanf() может прочитать.

char twenty_bytes[20] = "";
scanf("%s\n", twenty_bytes);
0 голосов
/ 20 января 2011

Предупреждение означает именно то, что написано: компилятор ожидает указатель на int, а не int при вызове scanf.

Быстрое исправление: замените age на &age, и все будет работать.

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

Чтобы получить указатель на переменную, добавьте к ней префикс &.Чтобы использовать переменную, на которую у вас есть указатель, добавьте к значению указателя *.

В этом случае вы хотите, чтобы scanf изменил значение age, поэтому вам нужно передатьэто указатель.

0 голосов
/ 20 января 2011

Я предполагаю, что он жалуется на строку scanf("%d\n", age); Проблема в том, что scan f ожидает указатель на вашу переменную, а не на переменную. Вам нужно получить адрес переменной, добавив '& `, и все будет в порядке.

0 голосов
/ 20 января 2011

Это означает, что он ожидает «int *» (то есть: указатель на целое число), но вы даете ему «int», которое является целым числом.Чтобы исправить это, добавьте & к age в строке scanf, чтобы оно стало.

scanf ("% d \ n", age);

...