Путаница с адресом массива C - PullRequest
11 голосов
/ 29 апреля 2009

Скажем, у нас есть следующий код:

int main(){
    int a[3]={1,2,3};
    printf("      E: 0x%x\n", a);
    printf("  &E[2]: 0x%x\n", &a[2]);
    printf("&E[2]-E: 0x%x\n", &a[2] - a);
    return 1;
}

При компиляции и запуске результаты выглядят следующим образом:

      E: 0xbf8231f8
  &E[2]: 0xbf823200
&E[2]-E: 0x2

Я понимаю результат & E [2] , который равен 8 плюс адрес массива, поскольку индексирован 2 и имеет тип int (4 байта в моей 32-разрядной системе), но я не могу выяснить, почему последняя строка 2 вместо 8?

Кроме того, какой тип последней строки должен быть - целочисленный или целочисленный указатель?

Интересно, это система типа C (своего рода кастинг) делает эту причуду?

Ответы [ 8 ]

10 голосов
/ 29 апреля 2009

Вы должны помнить, что на самом деле означает выражение a[2]. Это в точности эквивалентно *(a+2). Настолько, что совершенно законно писать 2[a] с одинаковым эффектом.

Чтобы это работало и имело смысл, арифметика указателей учитывает тип объекта, на который указывает. Но об этом позаботятся за кулисами. Вы можете просто использовать естественные смещения в своих массивах, и все детали просто срабатывают.

Та же логика применяется к различиям указателей, что объясняет ваш результат 2.

В этом примере индекс умножается на sizeof(int), чтобы получить смещение в байтах, которое добавляется к базовому адресу массива. Вы раскрываете эту деталь в двух ваших отпечатках адресов.

8 голосов
/ 29 апреля 2009

При вычитании указателей одного и того же типа результатом является количество элементов, а не количество байтов. Это сделано для того, чтобы вы могли легко индексировать массивы любого типа. Если вы хотите количество байтов - приведите адреса к символу *.

7 голосов
/ 29 апреля 2009

Когда вы увеличиваете указатель на 1 (p + 1), указатель указывает на следующий действительный адрес, добавляя (p + sizeof (Type)) байтов к p. (если Тип - int, тогда p + sizeof (int))

Аналогичная логика справедлива и для p-1 (в данном случае, конечно, вычитается).

Если вы просто примените эти принципы здесь:

Проще говоря:

a[2] can be represented as (a+2)
a[2]-a      ==>  (a+2) - (a)    ==> 2

Итак, за сценой,

a[2] - a[0]  
==> {(a+ (2* sizeof(int)) ) - (a+0) }  / sizeof(int) 
==> 2 * sizeof(int) / sizeof(int) ==> 2
5 голосов
/ 29 апреля 2009

Строка & E [2] -2 выполняет вычитание указателя, а не целочисленное вычитание. Вычитание указателя (когда оба указателя указывают на данные одного типа) возвращает разницу адресов, разделенную на размер типа, на который они указывают. Возвращаемое значение - int.

Чтобы ответить на ваш вопрос «обновления», снова выполняется арифметика указателя (на этот раз добавление указателя). Так сделано в C, чтобы упростить «индексирование» фрагмента смежных данных, на которые указывает указатель.

2 голосов
/ 29 апреля 2009

Вас может заинтересовать Арифметика указателей В C вопросы и ответы.

в основном операторы + и - учитывают размер элемента при использовании в указателях.

1 голос
/ 29 апреля 2009

Re: «Кроме того, какой тип последней строки должен быть? Целочисленный или целочисленный указатель ??»

целое число / число. по тому же признаку: сегодня - 1 апреля = число. не дата

1 голос
/ 29 апреля 2009

При добавлении и вычитании указателей в C вы используете размер типа данных, а не абсолютные адреса.

Если у вас есть указатель типа int и вы добавите к нему число 2, он увеличится на 2 * sizeof (int). Таким же образом, если вы вычтете два указателя типа int, вы получите результат в единицах измерения sizeof (int), а не в разнице абсолютных адресов.

(Наличие указателей, использующих размер типа данных, очень удобно, так что вы, например, можете просто использовать p++ вместо необходимости каждый раз указывать размер типа: p+=sizeof(int).)

0 голосов
/ 29 апреля 2009

Если вы хотите увидеть разницу в байтах, вам потребуется тип размером 1 байт, например:

printf("&E[2]-E:\t0x%x\n",(char*)(&a[2])-(char*)(&a[0]))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...