2013-12-11 3 views
2
#include<stdio.h> 
#include<stdlib.h> 
int main(int argc, char *argv[]) 
{ 
    int x = 2; 
    int *pointer2 = &x; 
    int number = &x; 
    printf("%x\n",number); 
    printf("%x\n",number+1); 
    printf("%x\n",pointer2); 
    printf("%x\n",pointer2+1); 

    return EXIT_SUCCESS; 
} 

Я получаю предупреждение от ССЗА, что «инициализация делает целое число от указателя без приведения [по умолчанию включено]» для переменного числа, но когда я компиляцию я получаю следующий вывод:Адресация в C

5da24540 
5da24541 
5da24540 
5da24544 

Очевидно, что вышеизложенное не происходит, поскольку мы можем видеть на первых двух строках вывода, что адрес увеличивается только на 1, а на 4 во втором случае. Также объясните, что & возвращает адрес, который может быть назначен другим переменным как int или это указатель в нем, который может быть назначен только для типа указателя.

+0

Выход, который вы получаете, является нормальным. Если вы добавите X в указатель на Y, тогда X * sizeof Y будет добавлен к указателю. Размер int равен 4 (по крайней мере, в вашем случае), поэтому вы получаете 5da24544 вместо 5da24540. –

+0

Оператор '&' дает указатель. Значение указателя называется адресом. Адрес также может рассматриваться как произвольное целочисленное значение, но вы обычно не выполняете числовые манипуляции на адресе, кроме как для взаимодействия с оборудованием, которое проверяет адреса за пределами ядра ЦП. – Potatoswatter

ответ

1

предупреждение из-за этого задания:

int number = &x; 

Вы Назначив int* к int, что Вы ничего не должны делать. Либо (1) присвойте значение xnumber, либо (2) измените номер number на номер int* (ссылка pointer2) и назначьте адрес x.

Или (3), если вы действительно хотите присвоить адрес x по номеру number при помощи машинного перевода.

// (1) 
int number = x; // Assign value of x. 
// (2) 
int* number = &x; // Assign address of x. 
// (3) 
int number = (int)&x; // Assign address of x and cast to int. 

Ваш второй вопрос связан с указателем арифметика.

Ваш number переменная является int, что означает, если вы увеличивать его (+ 1) он буквально увеличивается на 1.

Ваш pointer2 переменной является int*, что означает, если вы увеличивать его он увеличивается на величину int* (4 байта на 32-битных системах, 8 байт на 64-битных системах).

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

Есть две причины, по которым компилятор выдает предупреждение:

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

2) Еще одна причина, по которой стандарт запрещает это, заключается в том, что int составляет 4 байта (в большинстве реализаций) и int* может быть 4 или 8 байтов в зависимости от скомпилированной платформы.

+0

so & x не только возвращает адрес x, но & x сам по себе является указателем типа i.e здесь int *? – user2688772

+0

Да, '&' получает адрес переменной и добавляет один уровень косвенности к типу, т. Е. 'Int * y = & x; int ** z = & y; 'и т. д. –

+0

(3) дает предупреждение: предупреждение: отбрасывается из указателя в целое число разного размера, может быть из-за того, что sizeof (int *) составляет 8 байт, а sizeof (int) - 4 байта на моей машине. – user2688772

-1

напечатанный материал 'Число' назначение и попробовать, как это,

int x = 2; 
int *pointer2 = &x; 
int number = (int)&x; 

Это будет работать.

7

number является int, инициализирован с адресом x (делает int от адреса «без броска» - предупреждение говорит вам, что это, вероятно, не то, что вы хотите) - если увеличить его, он будет увеличиваться на один.

pointer2 является указателем на int (инициализируется с тем же адресом x), увеличивающиеся он увеличивает размер по из int (такое поведение называется «указателем арифметика»).

0

Компилятор не преобразовывает число из int в указатель. Предупреждение говорит «сделать целое число от указателя», а не «Сделать указатель из целого», поэтому number по-прежнему является int. Это указатель (адрес x), который был «преобразован» в простое целое число.

0

Вы получаете предупреждение, потому что не гарантировано, что тип int может содержать значение указателя (например, вы находитесь в системе, где int - 16 бит, но значения указателя - 32 бита); если добавить оттенок, компилятор, что вы знаете, что вы делаете (даже если вы этого не сделаете):

int number = (int) &x; 

Это говорит компилятору, что да, вы действительно хотите, чтобы взять адрес x и рассматривать его как обычное целое число. Просто имейте в виду, что значение, которое хранится до number, может быть усечено.

Также не гарантируется, что все типы указателей имеют одинаковый размер и представление; IOW, указатель на int может отличаться от указателя на char, который может отличаться от указателя на struct. На большинстве современных настольных и серверных архитектур они одинаковые, но есть еще некоторые нечетные архитектуры, где они не являются.

А почему вы получили разные результаты на добавлениях ...

Добавление 1 к указателю дает адрес следующего объекта из указываемого типа; IOW, если у вас есть указатель на int, добавление 1 даст вам адрес следующего доступного int, который составляет sizeof (int) байт с текущего адреса. Если у вас есть указатель на 10-элементный массив из int, добавление 1 даст вам адрес следующего 10-элементного массива из int, который составляет 10 * sizeof (int) байт с текущего адреса.

Это то, как работает индексация массива. Выражение a[i] интерпретируется как *(a + i); то есть вычислить адрес элемента ', следующего за a, и разыграть результат.

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