2015-12-10 2 views
3
#include <stdio.h> 
    int main(void) 
    { 
     int a[]= {15, 14, 34, 46, 69, 86, 10, 0, 4}; 
     int *p = a; // p point to the first element of array a[0] 
     printf("%x\n%x\n",&p+1, &a[0]); 
     return 0; 
    } 

, что код будет печатать, как напримерпочему & р + 1 дают тот же результат, что и р

bff0e554 
bff0e554 

так & р + 1 возвращает адрес первого элемента массива. Как я понимаю, & p возвращает адрес этого указателя и & p + 1 должен печатать адрес указателя + 1, пожалуйста, сообщите мне, что я пропустил !!

+2

Массив не является указателем, а не массивом. '& p' является ** адресом **' p'. – Olaf

+4

Совпадение. Вы путаете 'p + 1' и' & p + 1'. Так получилось, что 'p' хранится так, что один после' p' является началом массива. Отмените порядок деклараций или введите другой массив между ними или некоторые другие указатели или почти все, что изменит расположение переменных в стеке, и ваши печатные значения больше не совпадут - это совпадение, которое они делают. –

+0

@JonathanLeffler; Это может быть совпадением, но вы не должны игнорировать UB в этом месте. – haccks

ответ

3

Это смешно. Запишите точно что & p + 1 означает. Он не имеет ничего общего с любыми адресами в массиве a. То, что он печатает, - это чистое совпадение.

Добавить другой массив b. Затем установите p = b и напечатайте & p + 1 и & b [0]. Может быть, вы выясните, что происходит.

+1

, как вы и Кей говорят, что это чистое совпадение, я сначала указал указатель, после чего результат изменился. Кстати, это было упражнение, предложенное учителем, он говорит, что & p + 1 == & a [0] в решении -_-) – Tel0s

+2

@corfto: Найдите лучшего учителя. –

+0

Сообщите своему учителю, что 'p' является глобальным (в то же время позволяя' a' быть локальным), и попросите его объяснить, почему '& p + 1' нигде не находится рядом с' a'. (Хотя сначала проверьте, что сказал учитель, вы можете просто найти, что вы не интерпретировали его правильно.) – mah

6

&p принимает адрес p, а не значение p. Это для вас &p + 1 == a - это чистое совпадение и зависит от вашего выравнивания стека. Ваш компилятор мог бы отсортировать обе переменные в другом порядке или установить промежуток между ними.

+2

На самом деле даже нет необходимости иметь стек. – Olaf

3

Массив не является указателем, а не массивом.

&p является адресом p, не адрес он содержит (т.е. его значение), которое было бы p (FYI: значение объекта он указывает на это *p). Аналогично, &a[0] является адресом первого элемента массива. Это чистое совпадение, массив находится в следующем адресе (&p +1).

Кроме того, правильный указатель преобразования printf для указателей - %p, и он ожидает void * (вам необходимо указать здесь, поскольку это вариационная функция). Использование другого спецификатора вызывает неопределенное поведение.

Вы должны включить предупреждения компилятора. Современные компиляторы будут предупреждать о таких фундаментальных несоответствиях типов между строками формата printf (и) и аргументами.

+0

ерунда. Вы думаете о языках с более запоминающейся моделью памяти. В C массив - это просто блок выделенной памяти. Адрес первого элемента и адрес массива идентичны и (по модулю условие края с externs) '* (p + i) == a [i]'. –

+6

@CharlieMartin: Я больше ничего не писал. На вопрос и мой ответ даже не имеет значения, что они одинаковы. Однако, например, '& a' и' & a [0] 'все еще разные типы, поэтому это очень важно - просто не здесь (и я даже не говорю об этом). Я очень уверен, что знаю C очень хорошо и, конечно же, не имел «любимой модели памяти». Как вы прочтете это из ответа? – Olaf

+0

@CharlieMartin: Но я ценю неквалифицированные downvotes. Я не на лужайке! – Olaf

-3

Убедитесь, что вы используете то, что считаете себя. Я просто попробовал, и это сработало.

bash $ cc -o foo foo.c 
foo.c:6:23: warning: format specifies type 'unsigned int' but the argument has type 
     'int **' [-Wformat] 
    printf("%x\n%x\n",&p+1, &a[0]); 
      ~~  ^~~~ 
foo.c:6:29: warning: format specifies type 'unsigned int' but the argument has type 
     'int *' [-Wformat] 
    printf("%x\n%x\n",&p+1, &a[0]); 
       ~~   ^~~~~ 
2 warnings generated. 
bash $ ./foo 
58af0888 
58af0890 
bash $ 

Соблюдайте предупреждения, кстати.

+0

И да, у нас просто было несколько downvotes для показа результатов компиляции приведенного кода. –

+3

Совершенно исправлено. Вы не обращались к UB, и вы не объяснили, почему ** OP ** видит то же значение или почему вы этого не делаете. – Olaf

+0

@CharlieMartin OP ожидает, что первое значение откроет адрес 'a [1]', а второй - адрес 'a [0]'. Второе значение - это явная истина, но первое значение должно быть вторым значением плюс размер int ... это не значения, которые вы получаете. – mah

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