2016-05-11 3 views
4
int *(*table())[30]; 

Я не могу найти решение в любом месте. Что такое * table(), может ли это быть функцией или массивом?в C, что означает это объявление: int * (* table()) [30];

Не могли бы вы рассказать мне, что это значит?

+1

[объявить таблицу как функцию, возвращающую указатель на массив 30 указатель на INT] (HTTP: //cdecl.ridiculousfish.com?q=int+*(*table())[30]%3B) – ckruczek

+3

cdecl - ваш друг.'cdecl> explain int * (* table()) [30]' 'объявлять таблицу как функцию, возвращающую указатель на массив 30 указателя на int' – hobbs

+1

Пожалуйста, обратитесь к правилу по спирали/по часовой стрелке http://c-faq.com/ decl/spiral.anderson.html –

ответ

3

Чтение таких конструкций намного проще, если вы замените части декларации, которые могут быть заменены, с заменяющим именем. Скажем, f - это table(), что является функцией, принимающей неопределенное количество аргументов, а t - это тип int*.

Тогда декларация становится:

t(*f)[30]; 

, который, очевидно, является указателем на массив из 30 элементов t.

Заменить f, и мы получим функцию принимая неопределенное количество аргументов, и возвращает указатель на массив из 30 элементов т:

t(*table())[30]; 

Заменить t и мы получим функцию, принимая неопределенное количество аргументов и возвращает указатель на массив из 30 элементов указателя INT:

int*(*table())[30]; 
5

Вы можете расшифровать это изнутри:

int *(*table())[30]; 

Внутреннее связывание - это table(), что является функцией с неопределенными аргументами. Следующий уровень - *table(), поэтому table возвращает указатель на что-то. Следующий уровень - (*table())[30], поэтому он возвращает указатель на массив длиной 30 строк. Следующий уровень - *(table())[30], поэтому он возвращает указатель на массив указателей длиной 30 строк. На последнем уровне добавляется спецификатор типа, int *(*table())[30].

Таким образом, table является функцией (с неопределенными аргументами), которая возвращает указатель на массив длиной 30 строк указателей на int.

+0

Проходит ли оно до 30-го места в массиве указателей int или возвращает указатель массива длиной 30? –

+0

@DeBanana Поскольку это декларатор, 30 - длина массива, а не индекс. –

0

Линия:

int *(*table())[30]; 

заявляет, что «таблица является функция, возвращающая указатель на массив из 30 указателей на INT»

Есть много хороших статей о том, как читать декларации типа C. Here is one of them.

Резюмируя:

правил:

  1. Существует имя типа на левой стороне. Назовите это $ typename.
  2. Существует идентификатор где-то вправо, возможно, окруженный [] и () и *. Вызовите этот $ identifier.

Ваше заявление будет оформлено как: $identifier ... $typename.

  1. Начать с "$ identifier is (n)".

  2. Если вы можете пойти направо, воспользовавшись [...] или (...), добавьте это в свою декларацию. [...] - это (возможно, пустое) объявление массива, написанное «array (of ...)»; а (...) - это (возможно, пустое) объявление функции, написанное «возврат функции» или «возврат функции (...)».

  3. Если вы не можете идти правильно, потому что вы достигаете точки с запятой или запятой или закрывающей круглой скобкой, то вы должны идти влево. Идите влево, потребляя либо $ typename, если вы находитесь в конце процесса, либо потребляете декларацию указателя (*, написали «указатели (ов) на») или используете открывающую скобку. После использования любого из них, кроме $ typename, попробуйте снова пойти прямо.

    Помните: если хотите, пойдите направо, идите налево, если нужно.

Ваш вопрос, вновь

Имея это в виду, давайте снова посмотрим:

int *(*table())[30]; 

Шаг за шагом:

  1. $ имяТипа = "ИНТ"
  2. $ identifier = "table";
  3. Начните с "$ идентификатор (п)": "таблица (п)" ${typename} *(*${declaration}())[30];

  4. Идите направо: "... функция, возвращающая" ${typename} *(* ${declaration})[30];

  5. Идите направо: не удается, из-за )
  6. Идите налево: "... указатель (ей)" ${typename} * ${declaration} [30];
  7. Идите направо:»... массив 30" ${typename} * ${declaration};
  8. Идите направо: не удается, из-за ;${typename} * ${declaration}
  9. Идти влево: "... указатель (и) на" ${typename} ${declaration}
  10. Идти вправо: не удается.
  11. Идите налево: «ИНТ»

Пишут, что все в порядке, и вы получите:

таблица (п) функция, возвращающая указатель (ы) в массив 30 указателя (s) в целое

зачистить предложения путем удаления (s), где не требуется, и замена одного указателя с «указателем»:

table - это функция, возвращающая указатель на массив из 30 указателей на int.

0

Выше декларация может быть понята правилом по часовой стрелке/спирали.

enter image description here

Ниже описывается, как разобрать заявление, используя правило:

1) таблица является функцией с неуказанных аргументов.

2) стол() функция возвращает указатель .

3) указатель возвращенный таблицы() функции указывает на массив элементов.

4) Каждый элемент имеет тип целочисленных указателей т.е. каждый элемент указывает на целое число.

Подробнее о правиле хорошо описано в этой ссылке: The ``Clockwise/Spiral Rule''

0

Идентификатор таблицы это функция, которая возвращает указатель на массив из 30 целочисленных указателей. В качестве дополнения к изучению так называемого clockwise/spiral rule вы можете использовать сайт, например, http://cdecl.org/.

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

typedef int *(*Table)[30]; 

Table FooTable(void); 
Смежные вопросы