Вход с символьным указателем по сравнению с массивом символов

рассмотрите код

#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 только? я приношу извинения, если я не ясен.заранее спасибо:)

5
задан John Kugelman supports Monica 10 February 2015 в 03:51
поделиться

6 ответов

Потому что char* a; выделяет место в стеке для указателя символов, в то время как char a[100]; выделяет место для 100 символов.

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

Если вы используете &a, он запишет ваш ввод поверх самого указателя, в результате чего у вас останется указатель, указывающий неизвестно куда, что приведет к аварии номер два. Это при условии, что вы не ввели больше символов, чем переполнит указатель - это повредит стек вызовов, что приведет к еще одной аварийной ситуации (тип три).

И в качестве совета, пожалуйста, не используйте функции ввода, которые не имеют проверки границ, если только вы не контролируете, какие данные им предоставляются. Даже при char[100] кто-то может вызвать переполнение стека в вашем коде, введя больше символов, чем поместится в буфер.

Я считаю, что лучше всего использовать fgets (который может ограничить количество считываемых символов) в сочетании с sscanf (хотя если вы получаете только строку, sscanf не особо нужен).

9
ответ дан 18 December 2019 в 08:27
поделиться

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

2
ответ дан 18 December 2019 в 08:27
поделиться

В первом примере a - это «висячий указатель» - это указатель, который содержит адрес некоторой случайной области памяти. В большинстве случаев доступ к этому адресу приведет к сбою. Итог: вам нужно выделить память для файла.

1
ответ дан 18 December 2019 в 08:27
поделиться

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
Также, прежде чем начнутся комментарии... Это очень небезопасный код, но я полагаю, что вы просто пытаетесь разобраться с указателями, так что я просто попытался подтолкнуть вас в правильном направлении. (Если это не так, вам нужно изучить чтение ограниченного количества данных, убедиться, что они помещаются в ваши буферы, если они из какого-то другого источника, кроме файла, вам нужно убедиться, что вы получили их все, и так далее, и так далее).

4
ответ дан 18 December 2019 в 08:27
поделиться

Вы должны выделить память для a с помощью malloc () перед его использованием.

2
ответ дан 18 December 2019 в 08:27
поделиться

В вашем первом коде a - это неинициализированный указатель на char. Вы пытаетесь записать в невыделенную или зарезервированную память.

Вам необходимо выделить память для входной строки с помощью malloc () .


int main(void) {
  char* s;
  /* ... */
  s = malloc(100 * sizeof(*s));
  if (s == NULL) {
    return 1;
  /* ... */
}
1
ответ дан 18 December 2019 в 08:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: