Почему это присвоение переменной дает ошибку сегментации - PullRequest
0 голосов
/ 25 апреля 2020

Я пытаюсь получить символ из командной строки и вернуть этот символ и его значение ASCII. У меня есть функция, которая принимает целочисленный указатель и возвращает символ, который вводит пользователь. Целочисленный указатель указывает на значение int введенного символа. Однако, когда я пытаюсь присвоить значение указателя переменной в моем основном методе, это вызывает ошибку сегментации.

Код:

#include <stdio.h>
#include <stdlib.h>
char CharScan(int * iPtr);

void main(){
  int * iPtr;
  char exit;
  int aCode;
  char c;
  while(1){
    c = CharScan(iPtr);
    printf("got here 3\n");
    aCode = *iPtr;
    printf("got here 4\n");
    if(aCode == 27){
      printf("Exiting the code!\n");
      break;
    }
    else{
      printf("%c is ASCII code %d.\n", c, aCode);
    }
  }
}

char CharScan(int * iPtr){
  char c;
  printf("Enter a character: ");
  scanf(" %c", &c);
  printf("got here 1\n");
  int a = c;
  iPtr = &a;
  printf("got here 2\n");
  return c;
}

Выход:

Enter a character: a   
got here 1
got here 2
got here 3
Segmentation fault

Итак, ошибка возникает в строке:

aCode = *iPtr;

И я понятия не имею, что не так с этим утверждением.

1 Ответ

0 голосов
/ 25 апреля 2020

В языке программирования C используется система вызова функций передачи по значению, поэтому при вызове CharScan() для int *iPtr, CharScan() не получает какую-либо ссылку на iPtr, который вы объявили в main, ему просто передается копия любого указателя значение , которое в данный момент хранится в нем.

В вашем коде iPtr объявляется, но никогда не инициализируется, поэтому значение сохраняется в iPtr это фигня. C не определяет значение по умолчанию для переменных стека, поэтому в iPtr может храниться любое значение, и это значение мусора просто копируется для использования CharScan().

Строка в CharScan() который говорит, что iPtr = &a; не меняет значение iPtr в main, он только меняет значение CharScan() копии iPtr, и даже в этом случае значение &a не является что-то, что вы хотите сохранить, потому что a является переменной в стеке CharScan() и станет недопустимым местом в памяти, как только вернется CharScan().

Короче говоря, вы получаете сегментацию ошибка, потому что вы разыменовываете указатель мусора, который не был инициализирован.

Я написал бы код следующим образом:

#include <stdio.h>
#include <stdlib.h>

#define EXIT_CHAR 27
#define BUF_SIZE 100

int main(){
  char buf[BUF_SIZE];
  while(scanf("%s",buf)==1 && buf[0]!=EXIT_CHAR){
    printf("%c is ASCII code %d.\n",buf[0],(int)buf[0]);
  }
}

Код работает путем сканирования всей строки в буфер. Этот буфер представляет собой массив символов, который имеет некоторую произвольную емкость, достаточно большую, чтобы вместить разумную запись командной строки (я выбрал 100, но вы можете редактировать это значение). scanf() копирует всю строку в buf, но для остальной части l oop нас заботит только buf[0], который является первым символом в массиве. Если scanf() терпит неудачу, то scanf("%s",buf)==1 оценивается как ложное, l oop прерывается, и программа завершается. Если scanf() завершается успешно, но первый символ в строке - ASCII 27, тогда buf[0]!=EXIT_CHAR оценивается как ложное, l oop прерывается и программа завершается.

Если ни одна из этих вещей не происходит, то первый символ в строке печатается как char, затем как int, и scanf() пытается прочитать следующую входную строку в buf.

Надеюсь, это поможет! Ура!

...