Различение различных объявлений в C - PullRequest
1 голос
/ 16 марта 2019

Пока я просматривал свои вопросы, я нашел эти вопросы:

1) int*p;
2) int p(char*a)
3) int(*p(char*a))
4) int *p(void)
5) int*(*p[10])(char a)

(Пожалуйста, исправьте меня, если я не прав с моими ответами здесь.)

Q.1,объявляет целочисленную переменную-указатель 'p'

Q.2.объявляет функцию p с переменной-указателем char в качестве аргумента.

Q.4.объявляет пустой указатель (Возможно).

Может кто-нибудь ответить, что означают эти утверждения (и исправить мои ответы, если я ошибаюсь).Пожалуйста, ответьте как можно проще.Я довольно новичок в программировании.

Ответы [ 4 ]

2 голосов
/ 16 марта 2019

Основные правила:

T *p;        // p is a pointer to T
T *p[N];     // p is an array of pointer to T
T (*p)[N];   // p is a pointer to an array of T
T *p();      // p is a function returning a pointer to T
T (*p)();    // p is a pointer to a function returning T

T const *p;  // p is a non-const pointer to const T
const T *p:  // same as above
T * const p; // p is a const pointer to a non-const T

Деклараторы могут быть довольно сложными - этот список едва царапает поверхность.

Произвольно сложные деклараторы могут быть созданы путем подстановки:

T *p;  // p is a pointer to T
   |
   +—————+
   |     |
   v     v
T *(*a)[N]; // a is a pointer to an array of pointer to T
     |
     +————+
     |    |
     v    v       
T *(*f(int))[N];  // f is a function returning a pointer to an array of pointer to T
     |
     +—————+
     |     |
     v     v
T *(*(*g[M])(int))[N];  // g is an array of pointers to functions returning pointers to arrays of pointer to T

Функция signal в стандартной библиотеке C, вероятно, имеет самое неприятное объявление, которое вы можете увидеть в дикой природе:

void (*signal(int sig, void (*func)(int)))(int);

, которое читается как

       signal                                   — signal
       signal(                          )       — is a function taking
       signal(    sig                   )       —   parameter sig
       signal(int sig                   )       —      is an int
       signal(int sig,        func      )       —   parameter func
       signal(int sig,       *func      )       —      is a pointer to
       signal(int sig,      (*func)(   ))       —      a function taking
       signal(int sig,      (*func)(   ))       —        unnamed parameter
       signal(int sig,      (*func)(int))       —          is an int
       signal(int sig, void (*func)(int))       —      returning void
      *signal(int sig, void (*func)(int))       — returning a pointer to
     (*signal(int sig, void (*func)(int)))(   ) —   a function taking
     (*signal(int sig, void (*func)(int)))(   ) —     unnamed parameter
     (*signal(int sig, void (*func)(int)))(int) —       is an int
void (*signal(int sig, void (*func)(int)))(int) —   returning void
2 голосов
/ 16 марта 2019

Также:

Q3 int(*p(char*a)); похож на int* p(char*a); и объявляет функцию, получающую char* и возвращающую int*


Q5 int*(*p[10])(char a); определяетмассив из 10 указателей на функции, получающий char и returning an int * `

Пример:

int * g(char dummy)
{
  return NULL;
}

int*(*p[10])(char a) = { g }; /* entries 1..9 initialized to NULL */
2 голосов
/ 16 марта 2019

C декларации написаны бустрофедонным способом .

Он начинается все время справа.

4 первых объявления просты, я пишу только последнее

int*(*p[10])(char a)

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

(справа) p - это массив из 10 (слева) указателей на

...(*p[10])...

(справа) функции, которые принимают один параметр типа char и возвращают

...(...)(char a)

(вправо) указатель на (слева) int

int*(...)...

Итак, p is an array of 10 pointers to functions that take a single parameter of type char and return pointer to int

2 голосов
/ 16 марта 2019

Q.1.Правильно.

Q.2.Вы забыли упомянуть, что функция, когда вызывается, возвращает целое число, так что в теле программы можно записать целочисленное выражение, например p(a) + 1, но, в противном случае, правильное.

Q.4,Этот хитрый.Здесь у вас есть функция p(), которую можно вызывать без аргументов, но которая возвращает указатель на целое число;или, если вы предпочитаете сказать это по-другому, который возвращает адрес целого числа.В теле программы его можно использовать, например, как *p() + 1.

У вас все хорошо.Обычный способ чтения таких объявлений -

  • вправо от идентификатора p наружу, а затем, когда все модификаторы исчерпаны вправо,
  • влево отидентификатор p наружу.

Пример: 8765p1234.

Исключение составляют случаи, когда в скобки вокруг идентификатора вмешиваются, в этом случае: 87 (43p12)56.

Последнее становится хитрым, потому что существуют некоторые выражения, в которых сам идентификатор опущен, поэтому вы должны прочитать его как 87 (4312) 56.

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