2013-04-23 4 views
2

У меня есть пример программы следующим образом:Что происходит в C, когда я беру адрес указателя?

int testPointer(int * intArray, int * ptr) { 
    printf("%i\n", intArray); 
    printf("%i\n", ptr); 
    printf("%lu\n", &intArray); 
    printf("%lu\n", &ptr); 
    return 0; 
} 

int main() { 
    int result = testPointer((int *) 0x1, (int *) 0x2); 
    return 0; 
} 

Типичный результат будет:

1 
2 
3212962484 
3212962480 

Первые две строки всегда одинаковы, и я понимаю, как они производятся. Третья и четвертая строки различаются для каждого прогона, но значение на четвертой строке всегда на четыре меньше, чем значение на третьей строке. Как расшифровать эти значения? Что они представляют и почему последняя строка всегда на четыре меньше третьей?

+0

Это адреса памяти. –

+0

Преобразование '0x1' в' int * 'может быть неопределенным поведением. Избегайте неопределенного поведения. Да. Избегай меня. – Sebivor

+0

@undefinedbehaviour Преобразование '0x1' в' int * '- это неопределенное поведение? Почему это? – jogojapan

ответ

6

Он дает вам адрес этих переменных, то есть их расположение в памяти.

У вас есть эти переменные, которые являются аргументами функции, но они так же, как и любой другой локальной переменной в функции testPointer:

int testPointer(int * intArray, int * ptr) 
         ^^^^^^   ^^^ 

Они живут где-то в памяти, и вы получите адрес этого места с оператором & . Это похоже делает

int i; 
printf("%p\n", (void*)&i); 

, который показывает адрес переменной i.

Обратите внимание, что для печати указателя следует использовать% p, как в printf("%p\n", (void*)&ptr);,% i или% lu ожидает int или long аргумент, который может быть несовместим с указателем на данной платформе.

Что они представляют и почему это последняя линия всегда четыре меньше, чем третья линия

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

И мы могли бы также предположить из этого, что на вашей платформе, аргументы функции помещаются в стек слева направо (первая intArray, то ptr), если стек в системе растет вниз в памяти (что является наиболее часто встречающийся)

+0

'printf ("% p \ n ", &ptr);' также неверно. См. [Вопрос 5.17] (http://c-faq.com/null/machexamp.html). – Sebivor

+0

@undefinedbehaviour О, вы имеете в виду без ' (void *) 'cast. Ответ, похоже, был изменен, так что теперь это правильно. – jogojapan

1

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

+0

Это деталь реализации и не гарантируется стандартом C. – dan04

+0

Конечно, но некоторые традиции более сильные и более распространенные, чем другие , –

+0

@PieterGeerkens Конечно, но StackOverflow навсегда, и традиции в сфере ИТ меняются довольно часто. Стандарт C здесь, чтобы гарантировать, что эти изменения не влияют на то, как работает наш код. – Sebivor

1

Вы не расшифровываете эти значения. Это адреса, выбранные операционной системой и подпрограммами распределения памяти C для хранения ваших переменных. Это области памяти, которые система определила для вас.

Что еще вы хотите расшифровать?

+0

Звучит разумно, мне. Хотел бы я подумать, чтобы добавить это к моему ответу! – Sebivor

-1

Эти две строки являются адресами указателей в памяти. (вы должны использовать %p для их отображения).

Поскольку они два последовательных int*, переданные функции, они равны sizeof(int*) = 4 байта (в 32-разрядной системе).

+0

Что такое «32-разрядная система»? Является ли мой четырехъядерный процессор i7? – Sebivor

+0

@modifiablelvalue означает, что ваша программа использует [32 бит] (http://en.wikipedia.org/wiki/32-bit_application) = 4 байта для своих адресов памяти. Четырехъядерный i7 должен поддерживать адреса [64 бит] (http://en.wikipedia.org/wiki/64-bit_computing), но, возможно, вы используете 32-разрядную операционную систему или программное обеспечение. –

+0

Что делать, если я использую кросс-компилятор для создания 32-битного кода? Что делать, если я устанавливаю 32-разрядную ОС на свой четырехъядерный i7? Если у меня есть процессор DSP, где 'CHAR_BIT' равно 16, это 32-разрядное целое * 4 байта *? – Sebivor

0

Когда эта функция вызывается, int testPointer(int * intArray, int * ptr), значения intArray и ptr хранятся в стеке. Следовательно, &intArray напечатает указатель, который будет таким же, как указатель стека, который будет меняться для каждого запуска программы.

Когда передано 2 параметра, каждый параметр помещается в стек один над другим. Так, в 2 параметры помещаются рядом друг с друг с другом и размер указателя равен 4 байта, вы замечаете разницу 4.

0

Технически, поведение не определено, поскольку %lu директива должна соответствовать long unsigned int типизированных аргумента. Это может работать для вас, но только по совпадению. Вы не хотели бы привыкать полагаться на совпадение. Существуют реализации, в которых long unsigned int отличаются в представлении и ширине указателями, и этот код может привести к сбоям.

Если вы хотите напечатать эти адреса портативно, вам необходимо использовать директиву %p, которая соответствует аргументу void *. Не забудьте указать аргумент void *, потому что int * может отличаться от представления void *. См. Question 5.17 of c-faq.com.

Как расшифровать эти значения?

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

Что они представляют ...

Они мощь представляют смещение объектов, которые они указывают. Например, когда &intArray соответствует 3212962484, то может быть признаком того, что intArray находится по адресу 3212962484th байт в вашей ОЗУ. Однако полагаться на это было бы совпадением. То, как вы печатаете указатели, не переносимо, а указатели концептуально отличаются от целых чисел. Они также могут быть вашими номерами кредитных карт.

... и почему последняя строка всегда четыре меньше третьей строки?

Совпадение или выбор людей, которые разработали ваш компилятор, ОС или процессор. Четыре могут также быть the percentage of answers that fully respond to double-barreled questions.

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