Возможный дубликат:
Что означает этот оператор C?
Что означает это выражение?
char *(*c[10])(int **p);
Возможный дубликат:
Что означает этот оператор C?
Что означает это выражение?
char *(*c[10])(int **p);
c
- это массив из 10 указателей функций, которые возвращают char*
и принимают int**
в качестве аргумента.
(*c[10])
^^^^ = array of 10
(*c[10])
^ = function pointer
Итак, теперь у нас есть массив из 10 указателей на функции.
char *(*c[10])
^^^^^^ = returns a char*
char *(*c[10])(int** p)
^^^^^ = takes a int** as an argument
Массив из 10 указателей функций, которые возвращают a char*
и принимают a int**
в качестве аргумента.
ПРИМЕЧАНИЕ. Если вы пишете такой код, вы заслуживаете того, чтобы его ударили по лицу.
cdecl - отличный инструмент для перевода C
gibberish на английский
$ cdecl explain 'char * (*c[10]) (int **)'
declare c as array 10 of pointer to function (pointer to pointer to int) returning pointer to char
Некоторые примеры и фрагмент в конце, который использует decl.
void (*foo)(void);
Дает вам указатель на функцию foo
, который не принимает никаких параметров и ничего не возвращает.
Ex. A:
void fun_1(void)
{
...
}
foo = fun_1;
foo(); /* this would call fun_1() */
Ex. В:
char (*bar)(int);
Дает вам указатель на функцию bar
, который принимает 1 параметр как целое и возвращает a char
.
char fun_2(int x)
{
if (x == 50)
return 'a';
return 'Z';
}
char v;
bar = fun_2;
v = bar(50); /* this would call fun_2() with 50 as parameter and return 'a' */
int **p;
- указатель, указывающий на указатель типа int.
Ex. C:
int y[3] = {4, 3, 6};
int *w = &y[0];
int **z = &w;
printf("print: %d ", **z);
printf("%d ", *++(*z));
printf("%d\n", *(*z+1));
print: 4 3 6
Ex. D:
char *zez(char *s)
{
s = "def";
return s;
}
char *str = "abc";
printf("%s - ", str);
printf("%s\n", zez(str));
abc - def
Создание указателя на zez()
Ex. E:
char *(*ptr_zez)(char *);
ptr_zez = zez;
printf("ptr: %s - ", str);
printf("%s\n", ptr_zez(str));
ptr: abc - def
Ex. F:
char *(*c[10])(char *);
c[0] = zez;
printf("c[0]: %s - ", str);
printf("%s\n", c[0](str));
c[0]: abc - def
char *cumlade(int **p)
{
char *c;
int i;
if ((c = malloc(sizeof(char) * 7)) == NULL) {
fprintf(stderr, "Unable to reserve 7 bytes\n");
exit(0);
}
for (i = 0; i < 6; ++i) {
c[i] = (unsigned char)*(*p+i);
}
c[6] = '\0';
return c;
}
int main(void)
{
int t[3][3] = {{97 ,98, 99}, {100, 101, 102}};
int *u = &t[0][0];
int **v = &u;
char *ex;
char *(*c[10])(int **p); /* <-- the fun */
c[0] = cumlade;
c[1] = cumlade;
ex = c[0](v);
printf("EX: %s\n", ex);
free(ex);
ex = c[1](v);
printf("AX: %s\n", ex);
free(ex);
return 0;
}
EX: abcdef
AX: abcdef
c
- это массив указателей 10
для функций, переводящих указатель на int
в качестве своего параметра и возвращающий указатель на char
.
Объявление типа включает три оператора: массив [SIZE]
, указатель *
и функцию (type1 param1, type2 param2, ...)
. Помните, что все три оператора являются право-ассоциативными.
char *(*c[10])(int **p);
Добавьте более круглые скобки, чтобы сделать ассоциативность более понятной.
char *((*(c[10]))(int *(*p)))
Начните с c
, переменной.
c[10]
означает, что "c - это массив из 10 элементов, но каждый элемент является..."
Затем см. *
рядом с ним. *(c[10])
означает, что "c - это массив из 10 элементов, каждый элемент - указатель, указывающий на..."
Тогда (*(c[10]))(int *(*p))
означает, что "c - это массив из 10 элементов, каждый элемент является указателем на функцию, которая возвращает..." Используя аналогичные методы, мы видим, что функция принимает один параметр, который является "указателем на указатель к int".
Тогда *((*(c[10]))(int *(*p)))
означает, что "c - это массив из 10 элементов, каждый элемент является указателем на функцию, которая возвращает указатель на..."
Наконец char *((*(c[10]))(int *(*p)))
означает, что "c - это массив из 10 элементов, каждый элемент является указателем на функцию, которая возвращает указатель на char". Что это.
Я считаю, что Правило по часовой стрелке/спираль очень полезно. См. http://c-faq.com/decl/spiral.anderson.html
Но я бы предпочел добавить больше скобок, чем использовать спирали.
ok теперь ответ, который у вас есть, это массив указателя на функцию, но есть ли чистый (er) способ написать такой код? Да, есть, и я уверен, что этот код можно понять с первого взгляда:
typedef char *(*weirdFuncPtr)(int **p);
weirdFuncPtr funcPtrArray[10];
Btw. обычно я избегаю typdefs - я использую их при объявлении указателей функций. Это облегчает понимание такого кода C (C является аббревиатурой для Cryptic, не так ли?)
Он объявляет массив указателей функций. В массиве 10 элементов (из части [10] декларации). функция, на которую могут указывать эти указатели, вернет char * и принимает только один параметр. Указатель на указатель на integer (int ** p)
Взгляните на первый ответ на этот вопрос Как я могу использовать массив указателей на функции? там вы найдете еще один пример объявления массива функций-указателей, и это может привести к путанице.
Если вы ищете интуитивное объяснение этого, http://www.geeksforgeeks.org/archives/16841
Они объяснили это использованием оценки порядка постфикса, как и оценка выражения.