рассмотрите код
#include<stdio.h>
int main(void)
{
char* a;
scanf("%s",a);//&a and &a[0] give same results-crashes
printf("%s",a);
return 0;
}
почему это кодирует результаты в катастрофическом отказе? тогда как этот код с помощью символьного массива хорошо работает?
#include<stdio.h>
int main(void)
{
char a[100];
scanf("%s",&a[0]);//works fine
printf("%s",a);
return 0;
}
причем различием является символьный массив и указатель? но я знал, что указатель просто указывает на первый элемент, который является &a [0], должен хорошо работать, но верхние катастрофические отказы кода для всех трех, который является a, &a и &a [0]? главное, которое я был бы для сбора, состоит в том, как я могу взять вход символьного указателя, если я настаиваю на том, чтобы использовать scanf только? я приношу извинения, если я не ясен.заранее спасибо:)
Потому что char* a;
выделяет место в стеке для указателя символов, в то время как char a[100];
выделяет место для 100 символов.
В первом случае вам нужно выделить некоторую реальную память для указателя. Причиной вашего сбоя является то, что a
устанавливается в некоторое произвольное значение (вы его не инициализируете) и, когда вы scanf
, именно туда записываются данные. Если вы просто используете a
, назовем этот тип сбоя первым.
Если вы используете &a
, он запишет ваш ввод поверх самого указателя, в результате чего у вас останется указатель, указывающий неизвестно куда, что приведет к аварии номер два. Это при условии, что вы не ввели больше символов, чем переполнит указатель - это повредит стек вызовов, что приведет к еще одной аварийной ситуации (тип три).
И в качестве совета, пожалуйста, не используйте функции ввода, которые не имеют проверки границ, если только вы не контролируете, какие данные им предоставляются. Даже при char[100]
кто-то может вызвать переполнение стека в вашем коде, введя больше символов, чем поместится в буфер.
Я считаю, что лучше всего использовать fgets
(который может ограничить количество считываемых символов) в сочетании с sscanf
(хотя если вы получаете только строку, sscanf
не особо нужен).
scanf нужно место, куда поместить символы, которые он считывает. Вы можете передать ему указатель на массив символов (что вы делаете во втором примере) или указатель на память, полученную другим способом (скажем, malloc()). В вашем первом примере вы передаете ему неинициализированный указатель, поэтому возникают проблемы, которые вы наблюдаете.
В первом примере a - это «висячий указатель» - это указатель, который содержит адрес некоторой случайной области памяти. В большинстве случаев доступ к этому адресу приведет к сбою. Итог: вам нужно выделить память для файла.
a
ни на что не указывает. Или, на самом деле, он неинициализирован, так что он куда-то указывает, просто не на то, на что нужно.
Вы можете обеспечить хранение на стеке, как вы уже пробовали:
#include <stdio.h>
int main()
{
char x[100];
char *a = x; // a points to the storage provided by x on the stack
scanf("%s",a); // should work fine
printf("%s",a);
return 0;
}
Обратите внимание, что printf("%s",x);
дает точно такой же результат, a
указывает на x
, так что именно там будет "жить" ваша строка.
Или вы можете поручить управление памятью, используя malloc
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *a = malloc (100*sizeof(char)) // a points to the storage provided by malloc
if (a != null)
{
perror ("malloc"); // unable to allocate memory.
return 1;
}
scanf("%s",a); // should work fine
printf("%s",a);
free (a); // just remember to free the memory when you're done with it.
return 0;
}
HTH.
EDIT
Также, прежде чем начнутся комментарии... Это очень небезопасный код, но я полагаю, что вы просто пытаетесь разобраться с указателями, так что я просто попытался подтолкнуть вас в правильном направлении. (Если это не так, вам нужно изучить чтение ограниченного количества данных, убедиться, что они помещаются в ваши буферы, если они из какого-то другого источника, кроме файла, вам нужно убедиться, что вы получили их все, и так далее, и так далее).
Вы должны выделить память для a
с помощью malloc ()
перед его использованием.
В вашем первом коде a
- это неинициализированный указатель на char.
Вы пытаетесь записать в невыделенную или зарезервированную память.
Вам необходимо выделить память для входной строки с помощью malloc ()
.
int main(void) {
char* s;
/* ... */
s = malloc(100 * sizeof(*s));
if (s == NULL) {
return 1;
/* ... */
}