C указатели и адреса - PullRequest
       27

C указатели и адреса

1 голос
/ 12 апреля 2010

Я всегда думал, что * & p = p = & * p в C. Я попробовал этот код:

 #include <stdio.h>
 #include <stdlib.h>

 char a[] = "programming";
 char *ap = &a[4];  

int main(void)
{

 printf("%x %x %x\n", ap, &*(ap), *&(ap));   /* line 13 */
 printf("%x %x %x\n\n", ap+1, &*(ap+1), *&(ap+1));   /* line 14 */
}

Первая строка printf (строка 13) дает мне адреса:

40b0a8 40b0a8 40b0a8

, которые соответствуют ожидаемым.Но когда я добавил вторую строку printf, Borland жалуется:

"first.c": E2027 Должен получить адрес ячейки памяти в функции main в строке 14

Я ожидал получить:

40b0a9 40b0a9 40b0a9.

Кажется, что выражение * & (ap + 1) в строке 14 является виновником здесь.Я думал, что все три выражения указателя в строке 14 эквивалентны.Почему я не так думаю?

Второй связанный с этим вопрос: строка

char *ap = a;

указывает на первый элемент массива a.Я использовал

char *ap = &a[4];  

, чтобы указать на 5-й элемент массива a.

Является ли выражение

char *ap = a;

таким же, как выражение

char *ap = &a[0];

Последнее выражение только более многословно, чем предыдущее?

Большое спасибо ...

Ответы [ 4 ]

6 голосов
/ 12 апреля 2010

Вы можете взять только адрес lvalue , то есть выражение, которое относится к объекту. ap + 1 - это расчет адреса. Он имеет значение, но это временный объект, поэтому не является lvalue , и вы не можете взять его адрес.

В ответ на ваш второй вопрос в большинстве контекстов в выражениях массив распадается на указатель на свой первый элемент, поэтому да, char *ap = a; и char *ap = &a[0]; эквивалентны.

1 голос
/ 12 апреля 2010

Когда вы используете оператор ссылки C, он должен указывать на допустимое значение l, а не на произвольное выражение. Таким образом, &(ap+1) недопустимо, поскольку значение ap+1 является просто выражением, а не местоположением. Вы не можете сказать ap+1 = foo();

И да, a - это то же самое, что и & a [0] здесь. Обратите внимание, что * (a + b) на 100% эквивалентно a [b] (см. Верхний ответ на Странный язык для необычного примера этой эквивалентности). Получая указатель на член массива, вы можете использовать & array [i] или array + i. Пример:

struct foo array[5];
struct foo *item_3 = &array[3];
struct foo *also_item_3 = array + 3;

В этом случае, использовать array+i или &array[i] - дело стиля. &array[i], возможно, является лучшим выбором, так как более ясно, что элемент массива получен. Более того, & vec [i] работает с векторами C ++, а vec + i - нет.

0 голосов
/ 12 апреля 2010

Я считаю, что Чарльз прав насчет вашего основного вопроса, а вы правы относительно второго вопроса: char *ap = a; эквивалентно char *ap = &a[0];.

0 голосов
/ 12 апреля 2010

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

...