Еще один вопрос по указателю C - PullRequest
1 голос
/ 11 июля 2009

следующий код:

int *a;
*a = 5;

, скорее всего, приведет к ошибке сегментации, и я знаю, почему.

Следующий код:

int a;
*a = 5;

даже не скомпилируется. (gcc говорит: недопустимый аргумент типа унарного *).

Теперь указатель - это просто целое число, которое используется для хранения адреса. Итак, почему это должно быть проблемой, если я скажу:

*a = 5;

В идеале это также должно приводить к ошибке сегментации.

Ответы [ 6 ]

14 голосов
/ 11 июля 2009

Указатель не целое число. C имеет типы данных

а) предотвратить определенные ошибки программирования и

б) улучшить переносимость программ

В некоторых системах указатели не могут быть целыми числами, потому что они действительно состоят из двух целых чисел (сегмент и смещение). В других системах тип «int» не может использоваться для представления указателей, потому что int - это 32 бита, а указатель - 64 бита. По этим причинам C запрещает использовать целые числа как указатели. Если вы хотите использовать целочисленный тип, достаточно большой для хранения указателя, используйте intptr_t.

3 голосов
/ 11 июля 2009

Когда вы говорите

int a;
*a = 5;

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

*((int*)a) = 5;

.. и это говорит компилятору, что вы действительно, действительно хотите это сделать. НО - Это довольно рискованно. Зачем? Ну, например, в вашем примере вы никогда не инициализировали значение a, поэтому, когда вы используете его в качестве указателя, вы получите то значение, которое уже находится в местоположении, используемом для a. Поскольку это выглядит как локальная переменная, это будет не-init'd место в стеке фрейма функции, и может быть что угодно . По сути, вы пытаетесь записать значение 5 в какое-то неопределенное место; не очень мудрый поступок!

2 голосов
/ 11 июля 2009

Говорят, что он иллюстрирует, что указатели просто хранят адреса, и что адреса могут восприниматься как числа, во многом как целые числа Но обычно адреса имеют структуру (например, номер страницы, смещение внутри страницы и т. Д.).

Вы не должны понимать это словом. Целое число буквально хранит число, которое вы можете добавить, вычесть и т. Д. Но которое вы не можете использовать в качестве указателя. Целое число - это целое число, а указатель - это указатель. Они служат разным целям.

Иногда может потребоваться приведение от указателя к целому числу (для любых целей - может быть, в ядре ОС для выполнения некоторой адресной арифметики). Затем вы можете привести указатель к такому целочисленному типу, предварительно выяснив, гарантирует ли ваш компилятор правильные размеры и сохраняет ли значения. Но если вы хотите разыменовать, вы должны привести к типу указателя.

1 голос
/ 11 июля 2009

Вы никогда не назначаете «а» в первом случае.

int* a = ?
*a = 5; //BAD. What is 'a' exactly?

int a = ? //but some int anyway
*a = 5; //'a' is not a pointer!

Если вы хотите использовать целое число в качестве указателя, вам придется сначала его привести. Указатели могут быть целыми числами, но концептуально они служат различным целям.

0 голосов
/ 11 июля 2009

Оператор * является унарным оператором, который не определен для целочисленного типа данных. Вот почему утверждение

*a = 5;

не скомпилируется.

Кроме того, целое число и указатель - это не одно и то же. Как правило, они имеют одинаковый размер в памяти (4 байта для 32-разрядных систем).

0 голосов
/ 11 июля 2009

int * a - это указатель на int. Он нигде не указывает, вы его не инициализировали. Пожалуйста, прочитайте любую книгу о Си, прежде чем задавать такие вопросы.

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