Могут ли указатели вести себя как переменные? - PullRequest
1 голос
/ 01 сентября 2010

У меня путаница, связанная с этой программой.

#include <stdio.h>

int main(void)
{
        int value = 10;
        char ch = 'A';

        int* ptrValue = &value;
        char* ptrCh = &ch;

        int* ptrValue1 = value;
        char* ptrCh1 = ch;

        printf("Value of ptrValue = %d and value of ptrValue1 = %d\n", *ptrValue, ptrValue1);

        printf("Value of ptrCh = %c and value of ptrCh1 = %c\n", *ptrCh, *ptrCh1);
}

Я получаю два предупреждения при компиляции этой программы

unipro @ ubuguest: / SoftDev / ADSD / Module 1 /Модуль 1 / Rd / C / System $ cc charPointers.c -o charPointers
charPointers.c: В функции 'main':
charPointers.c: 11: предупреждение: инициализация делает указатель из целого числа без приведения
charPointers.c: 12: предупреждение: инициализация делает указатель из целого числа без приведения

И я знаю, что они означают.

При запуске программы я получаю следующую ошибку.

unipro @ ubuguest: / SoftDev / ADSD / Модуль 1 / Модуль 1 / Rd / C / System $ ./charPointers
Значение ptrValue = 10 и значение ptrValue1 = 10
Сегментацияошибка

Я знаю, что получаю ошибку при втором методе printf.

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

Спасибо.

Ответы [ 6 ]

5 голосов
/ 01 сентября 2010

При назначении

char* ptrCh1 = ch;

вы установите адрес 0x41, а не значение.Позже программа попытается отменить ссылку 0x41 (т.е. получить данные по адресу 0x41), что является недопустимым адресом.Следовательно, ошибка сегментации

2 голосов
/ 01 сентября 2010

Указатель хранит адрес чего-либо (или NULL). Таким образом, int * может хранить адрес int. Вы получаете адрес чего-либо с унарным оператором &.

Итак, что означает хранить 10 в указателе типа int? Ну, 10 не является адресом int, поэтому вы получаете предупреждение «инициализация делает указатель из целого числа без приведения», и так как вы храните в int * что-то еще, кроме адреса типа int, и пытаетесь разыменовать его , вы получаете неопределенное поведение.

В вашем случае, скорее всего, происходит то, что 10 интерпретируется как адрес памяти, и когда вы разыменовываете указатель, он выходит, чтобы получить все, что находится по этому адресу (адрес памяти 10 в вашем случае). Там, вероятно, ничего нет, эта область памяти не отображается, и вы segfault.

1 голос
/ 01 сентября 2010

Указатель указывает на область памяти (в которой вы можете сохранить некоторое значение). Здесь

    int* ptrValue1 = value;
    char* ptrCh1 = ch;

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

Обратите внимание, что во многих архитектурах допустимые области памяти начинаются с высокого смещения, поэтому небольшое целочисленное значение, например 10 или (значение ASCII) 'A', никогда не может указывать на допустимое расположение в памяти. Такие места с нехваткой памяти обычно зарезервированы / используются самой ОС (таким образом, они защищены от модификации - если вы попытаетесь, вы получите segfault). Обычно то же самое происходит, если вы пытаетесь получить прямой доступ к памяти, используемой другим процессом.

1 голос
/ 01 сентября 2010

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

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

0 голосов
/ 01 сентября 2010

Уверен, что он должен быть неисправен. Вы сохраняете любое значение в указателе (и, как вы говорите, компилятор предупреждал вас), а затем вы обращаетесь к нему, независимо от того, на что это указывает. Что еще вы ожидаете?

0 голосов
/ 01 сентября 2010

Это из-за *ptrCh1 в последней строке, вы пытаетесь разыменовать его.Удалите *, чтобы заставить его работать (хотя это не имеет особого смысла).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...