2013-07-15 2 views
8

Я только начал изучать C, и я использовал некоторые простые программы, используя MinGW для Windows, чтобы понять, как работают указатели. Я попытался следующие:Прямое присвоение значений C Указатели

#include <stdio.h> 

int main(){ 
    int *ptr; 
    *ptr = 20; 
    printf("%d", *ptr); 
    return 0; 
} 

который правильно составлен, но при запуске исполняемого файла он не работает - значение не выводится в командной строке, вместо этого я получаю сообщение об ошибке, которое говорит, что .exe файл перестал работать.

Однако, когда я попытался сохранения значения в переменной INT и назначить * PTR на адрес памяти этой переменной, как показано ниже:

#include <stdio.h> 

int main(){ 
    int *ptr; 
    int q = 50; 
    ptr = &q; 
    printf("%d", *ptr); 
    return 0; 
} 

он работает отлично.

Мой вопрос: почему я не могу напрямую установить буквальное значение указателю? Я смотрел учебники онлайн для указателей, и большинство из них делают это так же, как второй пример.

Любая помощь приветствуется.

+0

Причина, по которой указатель не инициализирован - он может указывать на почти везде и может привести к сбою программы. – Till

+1

Вам повезло, что он завершился ошибкой. – JonnyRo

+1

@ JonnyRo прав. В реальном коде эта ошибка обычно приводит к недельным отладкам, которые пытаются выяснить, почему какая-то другая переменная случайным образом изменяется каждый раз в то время (никогда, когда вы на самом деле проверяете ее, всегда, когда вы делаете публичная демонстрация) или эксплойты безопасности, когда кто-то устанавливает флаг «is_admin» в true, манипулируя разными значениями. – abarnert

ответ

20

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

Вам необходимо создать переменную int где-то в памяти для переменной int *.

Ваш второй пример делает это, но он делает другие вещи, которые здесь не актуальны. Вот самое простое, что вам нужно сделать:

int main(){ 
    int variable; 
    int *ptr = &variable; 
    *ptr = 20; 
    printf("%d", *ptr); 
    return 0; 
} 

Здесь переменная int не инициализирован, но это нормально, потому что вы просто заменить любое значение, был там с 20. Ключ состоит в том, что указатель инициализирован, чтобы указать на variable. На самом деле, вы могли бы просто выделить некоторую сырую память, чтобы указать, если вы хотите:

int main(){ 
    void *memory = malloc(sizeof(int)); 
    int *ptr = (int *)memory; 
    *ptr = 20; 
    printf("%d", *ptr); 
    free(memory); 
    return 0; 
} 
1

В первом примере, PTR не был инициализирован, поэтому он указывает на неопределенный ячейку памяти. Когда вы назначаете что-то в этом неуказанном месте, ваша программа взрывается.

Во втором примере адрес устанавливается, когда вы говорите ptr = & q, так что все в порядке.

7

Первая программа с комментариями

#include <stdio.h> 

int main(){ 
    int *ptr;    //Create a pointer that points to random memory address 

    *ptr = 20;   //Dereference that pointer, 
          // and assign a value to random memory address. 
          //Depending on external (not inside your program) state 
          // this will either crash or SILENTLY CORRUPT another 
          // data structure in your program. 

    printf("%d", *ptr); //Print contents of same random memory address 
          // May or may not crash, depending on who owns this address 

    return 0;    
} 

Вторая программа с комментариями

#include <stdio.h> 

int main(){ 
    int *ptr;    //Create pointer to random memory address 

    int q = 50;   //Create local variable with contents int 50 

    ptr = &q;    //Update address targeted by above created pointer to point 
          // to local variable your program properly created 

    printf("%d", *ptr); //Happily print the contents of said local variable (q) 
    return 0; 
} 

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

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

+1

Nice иллюстрации. – abarnert

Смежные вопросы