2011-09-15 4 views
-2

Кто-нибудь, пожалуйста, уточните, что здесь происходит?Двойной указатель в C

int main() 
{ 
    int **p = 0; 
//p=? and why| *p=? and why|**p=? and why 

    ++p; 
//p=? and why| *p=? and why|**p=? and why 

    printf("%d\n", p); 
return 1; 
} 

выход: - (почему?)

+3

«Почему» вы даже беспокоились –

+0

Комментарии коментариев меня путают. –

+0

@ Konrad: Я думаю, что комментарии кода путают автора кода. –

ответ

7

Прежде всего, p является указателем на указатель на целое число.

int **p = 0;

p = 0, *p = ничего, **p = меньше, чем ничего.

++p;

То же, что р = р + 1 означает размер одного указателя на указатель на INT далее. Указатель в основном, по крайней мере, на вашей ОС, длина 32 бит (4 байта). p теперь указывает на 4 байта после 0. Значение p равно .

+0

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

+2

+1 @ меньше, чем ничего – Aamir

+0

@NeXuS: пожалуйста, не редактируйте ответы, чтобы сказать что-то другое, это очень запутанно .. – Simon

4

Это понятно. У вас есть указатель на указатель на int (int **p означает указатель на указатель на int), который фактически содержит адрес 0). Указатель сам по себе в вашей архитектуре имеет длину 32 бита (4 байта), поэтому приращение p дает вам p + 4, то есть 0 + 4 = 4.

Пойдите, чтобы получить хорошую книгу C и узнать о указателе арифметика. Вы будете довольны остальной частью вашей жизни! :)

+0

+1 для '0 + 4 = 4' –

+0

Эй! Этот stackoverflow не только для тех, кто имеет хорошую концепцию. Может быть, у меня меньше знаний, но это не значит, что вы думаете, что все кругом и комментируете вот так. Я говорю о (идите с книгой C и узнайте об арифметике указателя. Вы будете довольны остальной частью вашей жизни!) –

+0

Я все еще не вижу, где проблема в обучении из хорошей C-книги об арифметике указателя. Из вашего вопроса можно сделать вывод, что вы недостаточно разбираетесь в этом вопросе. Извините, если это звучало грубо? Это было не мое намерение. –

6

p является указателем на указатель на int. Он инициализируется 0, т. Е. Это нулевой указатель.

Затем он увеличивается, указывая на следующий последовательный указатель-на-int в памяти. * Следующий указатель будет по адресу 4, потому что на вашей платформе размер указателя составляет 4 байта.

Затем printf интерпретирует значение указателя как целое число и отображает «4».

* Обратите внимание, что это теперь неопределенное поведение.

0

p является указателем на указатель на int. И он инициализируется 0, т. Е. NULL.

При увеличении его, теперь он указывает на следующий указатель на INT, который на 32-битных системах, случается 4.

3

++p фактически неопределенное поведение, но то, что, похоже, произошло от реализации что sizeof(int*) равно 4, а нулевой указатель - адрес 0. Напомним, что приращение указателя, когда оно не является UB, добавляет количество байтов к адресу, равному размеру типа referand. Поэтому не удивительно, что когда вы берете нулевой указатель типа int** (следовательно, тип referand равен int*) и увеличивайте его, вы попадаете по адресу 4. Это просто не гарантировано.

Передача указателя, когда формат %d ожидает int также неопределенное поведение, но кажется, что представление int и int** достаточно совместимы, и переменные аргументы, призывающие конвенции о вашей реализации относится к ним достаточно аналогичным образом, что он успешно напечатан 4. Это также не очень удивительно для реализаций, где sizeof(int) == sizeof(int**), но и не гарантируется.

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

+0

+1 для неопределенного поведения. –

+0

Поскольку существует два неопределенных поведения, это действительно только +0,5. –

+0

My +1 округлил его до +1 +1. – Tom