Что означают скобки в объявлении переменной C? - PullRequest
31 голосов
/ 28 октября 2008

Может кто-нибудь объяснить, что это значит?

int (*data[2])[2];

Ответы [ 5 ]

40 голосов
/ 28 октября 2008

Для чего нужны скобки?

В скобках C [] приоритет выше, чем у звездочки *

Хорошее объяснение из Википедии:

Чтобы объявить переменную как указатель на массив, мы должны использовать скобок. Это потому что в C скобки ([]) имеют более высокий приоритет чем звездочка (*). Поэтому, если мы хотим объявить указатель на массив, нам нужно указать круглые скобки, чтобы переопределить это:

double (*elephant)[20];

Это говорит о том, что слон указатель и тип, на который он указывает массив из 20 двойных значений.

Чтобы объявить указатель на массив указатели, просто объедините нотации.

int *(*crocodile)[15];

Источник .

И ваш фактический случай:

int (*data[2])[5];

данные - это массив из 2 элементов. Каждый элемент содержит указатель на массив из 5 дюймов.

Таким образом, вы можете использовать код с типом данных:

int (*data[2])[5];
int x1[5];
data[0] = &x1;
data[1] = &x1;

data[2] = &x1;//<--- out of bounds, crash data has no 3rd element
int y1[10];
data[0] = &y1;//<--- compiling error, each element of data must point to an int[5] not an int[10]
15 голосов
/ 28 октября 2008

Существует очень крутая программа под названием "cdecl", которую вы можете скачать для Linux / Unix и, вероятно, также для Windows. Вы вставляете объявление переменной C (или C ++, если вы используете c ++ decl), и оно прописывается в простых словах.

5 голосов
/ 29 октября 2008

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

Что значит

char *p;

действительно значит? Это означает, что *p это символ. Что значит

int (*data[2])[5];

означает? Это означает, что (*data[x])[y] является целым числом (при условии 0 <= x <2 и 0 <= y <5). Теперь просто подумайте о том, каковы последствия этого. <code>data должен быть ... массивом из 2 ... указателей ... на массивы из 5 ... целых чисел.

Тебе не кажется, что это довольно элегантно? Все, что вы делаете, это указывает тип выражения. Как только вы это поймете, декларации больше никогда не будут вас пугать!

«Быстрое правило» состоит в том, чтобы начать с имени переменной, сканировать вправо, пока не нажмете a), вернуться к имени переменной и выполнить сканирование влево, пока не нажмете (. Затем «выйти» из пару скобок и повторите процесс.

Давайте применим это к чему-то нелепому:

void **(*(*weird)[6])(char, int);

weird - указатель на массив из 6 указателей на функции, каждая из которых принимает аргумент char и int в качестве аргумента, а каждая возвращает указатель на указатель void.

Теперь, когда вы знаете, что это такое и как это делается ... не делайте это. Используйте typedefs, чтобы разбить ваши объявления на более управляемые куски. Э.Г.

typedef void **(*sillyFunction)(char, int);

sillyFunction (*weird)[6];
0 голосов
/ 12 марта 2014

Если у вас есть массив:

int myArray[5];
int * myArrayPtr = myArray;

Было бы вполне разумно. myArray без скобок - указатель на int. Когда вы добавляете скобки, вы, как и вы, обращаете внимание на указатель myArray. Вы могли бы написать ...

myArrayPtr[1] = 3;

Что вполне разумно. Использование скобок только затрудняет чтение и понимание IMO. И они показывают, что люди не понимают указатели, массивы и арифметику указателей, то есть как компилятор или компоновщик переходит от одного к другому. Похоже, что с круглыми скобками вы получаете проверку границ.

0 голосов
/ 29 октября 2008

data [2] - массив из двух целых чисел

* data [2] - указатель на массив из двух целых чисел

(* данные [2]) - "

(* data [2]) [2] - массив из 2 указателей на массивы из двух целых чисел.

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