2015-08-22 3 views
3

Это один из экзаменационных вопросов, и цель состоит в том, чтобы определить, что программа напишет. Я действительно смущен тем, что такое int (*f[])(int*) = {f1, f2, f2, f1 };. Я учил, что это может быть массив, элементами которого являются результаты функций в скобках, и эти результаты являются адресами, указывающими на int.Что означает int (* f []) (int *)?

Не могли бы вы объяснить это мне, пожалуйста?

А также, какой параметр делает функция f[i++] получить в

for (i=0; i<2; a += fx(f[i++], a));

Проблема:

int f2(int *p) { return *p-- + 2; } 

int f1(int *q) { return ++*q; } 

int fx(int (*pf)(int*), int q) { 
    int t = q; 
    while ((t = pf(&q)) % 2) q+=2; 
    return t; 
} 

#include <stdio.h> 

void main() { 
    int a = 4, b = 3, *p = &b, i; 
    int (*f[])(int*) = {f1, f2, f2, f1 }; 

    for (i=0; i<2; a += **fx(f[i++]**, a)); 
    printf("%d", a + *p); 
} 
+1

отступы! Отступы! Отступы! –

ответ

11

Применение clockwise/spiral rule

int (*f[])(int*) 
    ^    f is 

int (*f[])(int*) 
     ^^^    f is an array 

int (*f[])(int*) 
    ^^^^^^    f is an array of pointers 

int (*f[])(int*) 
    ^^^^^^^....^  f is an array of pointers to functions 


int (*f[])(int*) 
    ^^^^^^^^^^^^  f is an array of pointers to functions 
         that accept a pointer to int 

int (*f[])(int*) 
^^^^^^^^^^^^^^^^  f is an array of pointers to functions 
         that accept a pointer to int and return a int value 
+0

Ow большое спасибо! Просто еще одна вещь. Почему нет int (* f []) (int *), записанный как int (int *) (* f [])? Я имею в виду, для меня это имеет смысл. И может ли он быть написан таким образом? – CptWhoWent

+0

Хммм .... C был разработан таким образом, что * «декларация следует за использованием» *. Вы используете функции с синтаксисом 'obj = fx (parm1, parm2, ...);' и способ объявления указателей на функции следует этой структуре. – pmg

+0

Большое вам спасибо! – CptWhoWent

0

После the clockwise/spiral rule мы увидим, что f представляет собой массив указателей на функции , где каждая функция в массиве принимает аргумент int* и возвращает int.

Инициализация просто инициализирует этот массив некоторыми указателями на функции.

Зная, что такое f, должно быть полезно с другой проблемой.

4

Он объявляет f как массив указателей на функцию, которая возвращает int и принимает int * в качестве аргумента.

Существует правило старшинства для понимания сложных деклараций, которые рассматриваются в книге Expert C Programming: Deep C Secrets:

Старшинства Правило Понимание C декларации

  • A. деклараций считываются, начиная с имя, а затем чтение в порядке приоритета.

  • Б. Приоритет, от высокого к низкому, является:

  • В.1. скобки, группирующие вместе части декларации

  • B.2. операторы постфикса:
    круглые скобки () с указанием функции и
    квадратные скобки [] с указанием массива.

  • B.3. префиксный оператор:
    звездочка, обозначающая «указатель на».

  • С. Если const и/или volatile ключевое слово находится рядом с спецификатором типа (например int, long, etc.) Он относится к типу спецификатора.В противном случае ключевое слово и/или volatile применяется к звездочке указателя слева от нее.

Таким образом, он идет как:

 f       -- f (A) 
    f[]       -- is an array (B.1) 
    *f[]       -- of pointers to (B.3) 
    (*f[])()      -- function (B.2) 
(*f[])(int *)     -- that expects a pointer to an int as an argument 
int (*f[])(int*)    -- and return an int  

Я хотел бы предложить, чтобы избежать спиральных правил, как это fails в некоторых случаях, например, в случае int* a[10][15];.

0

Этот

int (*f[])(int*) = {f1, f2, f2, f1 }; 

является декларация массива функциональных указателей типа Int (Int *), который имеет функции, которые имеют тип возвращаемого int и один параметр типа int *.

Как f является массивом, то f[i++] является элементом массива, который имеет одно из значений f1, f2 и т. Д.

Эта функция

int fx(int (*pf)(int*), int q); 

имеет два параметра: указатель на функцию, которая имеет тип INT (INT *) и объект типа междунар.

Так это выражение

fx(f[i++], a) 

является вызов функции, которая accespts в качестве аргументов одного из указателей на функции f1, f2 и так далее, и объект a

2

Давайте считать, что отдельно с помощью удивительный C gibberish to English website:

int (*f[])(int*) 

DECLARE е в виде массива указатель функция (указатель на int), возвращающая int

f - это массив указателей функций.

следовательно, используя инициализатор массива {} для хранения функций в нем довольно ясно.

0

Он по существу определяет массив указателей на функции. Ниже перечислены:

int (*f[])(int*) = {f1, f2, f2, f1}; 

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

int (*)(int*) 

который является указателем функции для функции, которая принимает один аргумент типа int * и возвращает int.

Тело цикла for состоит из пустой инструкции.Вы можете переписать его для большей ясности, как:

for (i = 0 ; i < 2; a += fx(f[i++], a)) 
    ; 

Есть две итерации для i = 0 и i = 1. Каждый раз, когда a увеличивается на результате вызова функции:

fx(f[i++], a) 

Первый аргумент является адрес функции, которая хранится в массиве f. Это f[0] и f[1] соответственно (то есть f1 и f2). Вы можете использовать эквивалентную форму:

fx(&f[i++], a) 

но не было бы реальной разницы (это просто вопрос предпочтения).

Если это выглядит слишком странно или сложным для вас, то вы можете переписать for петлю как:

for (i = 0 ; i < 2; a += fx(f[i], a), i++) 
    ; 

, а также:

for (i = 0 ; i < 2; i++) 
    a += fx(f[i], a); 
1

В отличие от обычного метода обучения, я предлагаю вам начать с за пределами в. Признайте общую структуру декларации и приступайте к уточнению: замените крупнозернистые «капли», которые вы видите более подробными. Другими словами, переходите синтаксис из корня дерева синтаксиса к листьям, вместо того, чтобы пытаться выбрать правильный лист и работать снизу вверх.

Общая структура декларации (которая имеет один описатель) является:

TYPE WHATEVER; 

WHATEVER в настоящее время объявлены, связанные с TYPE.

Обратите внимание, что TYPE является int, поэтому WHATEVER имеет тип int. И WHATEVER имеет общую форму (W1)(W2): две синтаксические единицы в скобках, независимо от 1 и всех 2:

int (W1)(W2); 

Здесь, W1 является то, что объявляется, и это функция, возвращающая int, которая выводится список W2 параметров , Последнее фактически означает int *:

int (W1)(int *); 

Таким образом W1 является функция, возвращающая int который принимает int *. Но W1 на самом деле *W3, что делает W3 указателем на W1.

int (*W3)(int *); 

W3 является указателем на функцию, возвращающую int который принимает int *.

И W3 на самом деле f[], так f массив неопределенного размера типа W3 «s:

int (*f[])(int *); 

f массив неопределенного размера указателей на функцию, возвращающую int, который принимает int *.

Совет: Как мы знаем, что W1 это на самом деле не W3[] где W3 тогда *f? Это связано с тем, что оператор построения типа [...] синтаксически подобен оператору индексирования постов постфиксации [...], а построение типа * аналогично унарному оператору разыменования *. Унарный оператор имеет нижнюю предопределенность , чем оператор постфикса. Когда мы видим *X[], мы знаем, что это означает *(X[]), а не (*X)[]. Символы *X не образуют синтаксическую единицу в этой фразе. Если мы хотим второго значения, мы должны использовать круглые скобки.

дерево синтаксис:

      declaration 
          |  | 
       +------------+  +----------------+ 
       |         | 
specifier-qualifier list -- TYPE    declarator -- WHATEVER 
       |        |  | 
       int       +-----+  | 
              |    | 
            function -- W1 params -- W2 
              |    | 
             pointer -- W3 (int *) 
              | 
             array -- f 

Внимательные символы, такие как W3 только этикетки для узлов при обходе от корня к листьям. Имя, объявленное в объявлении C, находится где-то внизу дерева, в отличие от некоторых других языков. По мере того как go deeper в Дерево, мы на самом деле начинаем из типа, поэтому, наконец, когда мы приходим на дно, мы знаем самые важные вещи: объявляется f, и в целом это массив чего-то.