Почему scanf не работает должным образом при записи в строковый литерал?
include<stdio.h>
int main()
{
//char b[10];
char *a="goodone";
//a=b;
scanf("%s",a);//this scanf fails and thow segmentation fault.
printf("%s",a);
}
Почему это не работает? Я много пробовал с этим scanf, но, когда я резервирую память для своей переменной a * (назначая a = b (прокомментированный)), она отлично работает. В противном случае это не так.
Я считаю, что char * a выделит некоторую память для своей строки ( "goodone" ) и вернет эту ячейку памяти в ее значение. И printf отлично работает с этой верой, почему scanf нет?
пожалуйста, спаси меня от этого....
Ответы
Ответ 1
Это потому, что вы инструктируете scanf
записывать данные, которые он считывает, в память, выделенную для значения const char*
, то есть в постоянную память.
Если вы хотите, чтобы ваша строка была постоянной для записи, измените
char *a="goodone";
к
char a[]="goodone";
Обратите внимание, что это также небезопасно: он может упасть, когда пользователь вводит более семи символов. Добавьте ограничение к вашему спецификатору формата, чтобы решить эту проблему:
scanf("%7s",a);
P.S. Закомментированный a=b
работает отлично, потому что он не изменяет строчную константу; скорее, он изменяет указатель на константу символа, который разрешен.
Ответ 2
char *a
- это просто указатель на char
. Когда вы назначаете ему "goodone"
, он указывает на этот строковый литерал (который доступен только для чтения) и scanf
пытается перезаписать эту строку в памяти, которая вызывает сбой.
Если вы назначили ему b
, то у вас есть a
, указывающий на область записи для записи размером 10 char
(т.е. строку с максимальной длиной 9 + завершающий NUL). Поэтому он работает до тех пор, пока scanf
не хранит ничего дольше, чем там.
Аналогичным образом вы можете сделать a
массив вместо указателя (т.е. char a[] = "goodone";
). Снова вам нужно следить за тем, чтобы не хранить там дольше.