Разница между двумя объявлениями, включающими указатель и массив - PullRequest
1 голос
/ 30 октября 2008

В чем разница между int *a[3] и int (*a)[3]?

Ответы [ 5 ]

19 голосов
/ 30 октября 2008

Нет разницы между int a[3] и int (a)[3], они оба объявляют a как массив из 3 int с. Существует разница между int *a[3] и int (*a)[3], первый объявляет массив из 3 указателей на int, тогда как второй объявляет указатель на массив из 3 int с. Скобки имеют значение здесь, потому что в С скобки имеют более высокий приоритет, чем *.

9 голосов
/ 30 октября 2008

В качестве альтернативы вы можете использовать cdecl, который выводит значение объявления переменных на английском языке.

cdecl> explain int*a[3]

объявить массив 3 указателем на int

cdecl> explain int (*a) [3]

объявить как указатель на массив 3 из int

7 голосов
/ 30 октября 2008

Если у вас есть какие-либо сомнения, использование этого трюка с g ++ часто удобно:

#include <iostream>

template < class T > void describe(T& )
{
  // With msvc, use __FUNCSIG__ instead
  std::cout << __PRETTY_FUNCTION__ << std::endl;
}

int main(int argc, char* argv[])
{
  int *a[3];
  describe(a);

  int (*b)[3];
  describe(b);

  return EXIT_SUCCESS;
}

Скомпилируйте его с помощью g ++ и запустите, вы получите:

void describe(T&) [with T = int*[3]]
void describe(T&) [with T = int (*)[3]]

Итак, они определенно НЕ одинаковы! Что у вас есть:

  1. массив из 3 указателей на int.
  2. указатель на массив из 3-х объектов.
6 голосов
/ 30 октября 2008

Кажется, ваши звездочки потерялись при форматировании ...

int *a[3]

объявляет массив 3 int*.

int (*a)[3]

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

int foo[3];
int bar[3];
int (*vp)[3];
vp = &foo;
(*vp)[0] = 0;
3 голосов
/ 17 июля 2009

Существует статья превосходная по этому URL при чтении объявлений типа C. Автор, Эли Бендерский, дает простой метод для чтения деклараций. Вы начинаете с имени переменной, а затем двигаетесь вдоль линии, произнося то, с чем вы сталкиваетесь, когда вы идете. Основной метод - начать с имени переменной и идти вправо. Я приведу простой обзор, но я настоятельно рекомендую вам прочитать статью.

  1. Начинайте с имени переменной и двигайтесь вправо.
  2. Если вы нажмете правую пареню ) или точку с запятой ;, то вернитесь туда, откуда вы начали идти направо, а затем - налево.
  3. Если вы столкнулись с левой пареной ( во время движения вправо, то вы столкнулись с объявлением function , и далее следует список аргументов через запятую. Примечание : вы встретите правую часть в конце списка аргументов. Приведенное выше правило не распространяется на это право.
  4. Если вы встретите левую скобку, прочитайте ее как «массив».
  5. Пройдя налево, когда вы нажмете левую парену (, затем вернитесь в правую пареню, где вы в последний раз шли направо. Перепрыгни через правую пареню и продолжай повторять.
  6. [Повтор]

Итак, применяя это правило к вашей конкретной проблеме ...

В объявлении "int * a[3];", a - имя переменной. Итак, читается:

a - это массив ([) из 3 элементов ([3]) указателей (*) на целые числа (int)

В объявлении "int (* a)[3];", a - имя переменной. Итак, читается:

a - указатель (*) на массив ([) из 3 элементов ([3]) целых чисел (int)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...