Компьютерная помощь
Сайт комнаты "Компьютерная помощь"

Программирование на С

Программирование | 16 июля 2016 г.

Автор: Code_46

Существует правило по которому компилятор или точнее парсер разбирает выражение рассмотрим правило вправо-влево после него вам будет намного легче читать и понимать сигнатуры функций

Начните разбирать заголовок от имени функции сначала вправо если там закрывающая скобка ) то влево иначе вправо пока не встретим закрывающую скобку ) потом снова влево и в конце концов вы поймете смысл описания начнем с простого постепенно усложняя первый пример

void ( *func ( void ) ) ( void );

думаю стоит объяснить начинаем с func идем вправо первая ( скобка идем вправо пока не встретим ) скобку встретили на это этапе func это судя по тому что мы прошли ( void ) функция теперь влево от func пока не встретим ( скобку встретили увидели * значит func это функция кторая принимает ( void ) и возвращает указатель теперь снова вправо с того места до которого мы дошли в прошлый раз мы видим снова ( void ) значит func это функция которая возвращает указатель на функцию идем влево видим просто void значит func это функция которая возвращает указатель на функцию которая имеет тип void ниже рабочий пример

#include  void show (void)
{
    puts ("yes");
}
/* функция принимает аргумент типа void и  возвращает указатель на функцию принимающую void и возращающую void */

void (*func (void)) (void)
{
    return show;
}

int main (void)
{
    func ( )( );
    /* думаю надо пояснить func ( )( ); работает так сначала вызывается func ( );
    она вернет адрес функции а в Си имя и адрес функции одно и тоже
    и потом для адреса мы делаем ( ); тоесть просто вызываем вторую функцию
    причем запись func ( )( ); полностью корректна оператор ( ) выполняется
    слева направо никаких проблем не возникает (* func ( ))( );
    или можно так получаем адрес явно развменовываем и вызываем вторую функцию
    одно и тоже но видно сразу ход вычислений*/
}

усложним пример void (* func (void)) (char *);
начинаем разбирать func это функция которая ничего не принимает возвращающая указатель на функцию которая принимает аргумент типа символьной строки и имеет тип void

#include  void show (char * str)
{
    puts (str);
}
/* возвращает указатель на функцию принимающую строку и ничего не возвращающую */

void (* func (void))(char *)
{
    return show;
}

int main (void)
{
    func ( )("yes");
    (* func( ))("yes");
}

усложним void ( * func ( char * str ) ) ( char * ); func это функция которая принимает символьную строку и возвращает указатель на функцию которая принимает символьную строку и имеет тип void

#include  void show (char * str)
{
    puts (str);
}

void (* func (char * str))(char *)
{
    puts (str);
    return show;
}

int main (void)
{
    func ("no")("yes");
    (* func("no"))("yes");
}

усложним void (* func (char * str, int (*arr)[COL], int rows)) (char *); func это функция которая принимает аргумент типа символьная строка и указатель на массив из двух значений типа int и количество строк если представлять память как строки и столбцы вообще младшую размерность указывать ненадо ее можно или передать как в данном случаее или подсчитать sizeof *arr / sizeof (*arr)[0] получим количество строк при условии что arr указатель на массив а не на первый элемент массива разница огромная потому что мы пытаемся трактовать память как многомертный массив

#include  void show (char * str)
{
    puts (str);
}

void (* func(char * str, int (*arr)[COL], int rows))(char *)
{
    int i, j;
    puts (str);
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < COL; j++)
        {
            printf ("%d ", *(*(arr+i)+j));
            *(arr+i) //есть строка
            *(+j) //есть столбец
        }
        putchar ( '\n' );
        arr + i /* прибавляет к указателю не размер элемента, а
        * количество байт занимаемых одной строкой
        * так как arr указатель на массив а не первый элемент */
    }
    return show;
}

int main (void)
{
    int matrix [][2] = {{1, 2}, {3, 4}};
    func ("no", matrix, sizeof matrix / sizeof matrix[0])("yes");
    (* func("no", matrix, sizeof matrix / sizeof matrix[0]))("yes");
}

усложним char * (* func(char * str, int (*arr)[COL], int rows))(char *) ; func есть функция принимающая символьную строку указатель на массив из двух элементов типа int и количество строк возвращающая указатель на функцию которая принимает указатель на символьную строку и возвращает символьную строку

#include  char * show(char * str)
{
    puts(str);
    return "ended";
}

char * (* func(char * str, int(*arr)[COL], int rows))(char *)
{
    int i, j;
    puts(str);
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < COL; j++)
            printf ("%d ", *(*(arr+i)+j));
        putchar ('\n');
    }
    return show;
}

int main (void)
{
    int matrix[][2] = {{1, 2}, {3, 4}};
    func ("no", matrix, sizeof matrix / sizeof matrix[0])("yes");
    puts((* func("no", matrix, sizeof matrix / sizeof matrix[0]))("yes"));
}

усложним char (* (* func(char * str, int (*arr)[COL], int rows))(char *))[SIZE] ; func есть функция принимающая символьную строку указатель на массив из двух элементов типа int и количество таких массивов тоесть количество строк а макрос COL определен как 2 возвращающая указатель на функция которая принимает указвтель на символьную строку и возвращает указатель на массив из SIZE элементов типа int может быть неочевидно как мы к этому пришли рассмотри по шагам func идем вправо до ) в итоге видим func (char * str, int (*arr)[COL], int rows) функция принимающая символьную строку указатель на массив из двух элементов типа int и количество таких массивов потом идем влево видим (* func возвращающая указатель на идем вправо ( char * ) на функцию которая принимает строку идем влево видим ( * и возвращающая указатель на идем вправо видим [ SIZE ] указатель на массив из SIZE элементов идем влево видим char указатель на массив из SIZE элементов идем влево видим char типа char

#include
#define COL 2
#define SIZE 5
char (* show(char * str))[SIZE]
{
    static char hello [] = "tty0";
    char ( *g ) [ SIZE ] = &amp;
    hello;
    puts ( str );
    return g;
}

char ( * ( * func ( char * str, int (*arr)[COL], int rows ) ) ( char * ) )[ SIZE ]
{
    int i, j;
    puts ( str );
    for ( i = 0; i < rows; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%d ", *(*(arr+i)+j) );
        putchar ( '\n' );
    }
    return show;
}

int main ( void )
{
    int matrix [][COL] = {{ 1, 2 }, { 3, 4 }};
    func ( "no", matrix, sizeof matrix / sizeof matrix [ 0 ] ) ( "yes" );
    puts ( * ( * func ( "no", matrix, sizeof matrix / sizeof matrix [ 0 ] ) ) ( "yes" ) );
}

усложним по сути этот пример такой же только не указатель на массив символов возвращается а на матрицу целых чисел возвращается

#include
#define COL 2
#define SIZE 5

static int hello [][COL] = {{ 2000, 3000}, {4000, 5000 }};
int ( * show ( char * str ) )[COL]
{
    int (*g)[COL] = hello;
    puts ( str );
    return g;
}

int ( * ( * func ( char * str, int (*arr)[COL], int rows ) ) ( char * ) )[COL]
{
    int i, j;
    puts ( str );
    for ( i = 0; i < rows; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%d ", *(*(arr+i)+j) );
        putchar ( '\n' );
    }
    return show;
}

int main ( void )
{
    int (*p)[COL];
    int i, j;
    int matrix [][COL] = {{ 1, 2 }, { 3, 4 }};
    func ( "no", matrix, sizeof matrix / sizeof matrix [ 0 ] ) ( "yes" );
    p = ( * func ( "no", matrix, sizeof matrix / sizeof matrix [ 0 ] ) ) ( "yes" );
    for ( i = 0; i < sizeof hello / sizeof hello [ 0 ]; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%d ", *(*(hello+i)+j) );
        putchar ( '\n' );
    }
}

усложним mydata ( * ( * func ( char * str, int (*arr)[COL], int rows ) ) ( char * ) )[COL] ; func есть функция принимающая символьную строку указатель на массив из COL элементов типа int считай столбцов и количество строк кторая возвращает указатель на идем вправо функцию котоая принимае символьную строку влево идем и возвращает указатель на вправо идем указатель на массив из COL элементов вправо идем типа mydata

#include
#define COL 2
#define SIZE 5

typedef struct _mydata
{
    char my [ SIZE ];
} mydata;

mydata hello [][COL] = {{ "2000", "3000"}, {"4000", "5000" }};
mydata ( * show ( char * str ) )[COL]
{
    mydata (*g)[COL] = hello;
    puts ( str );
    return g;
}

mydata ( * ( * func ( char * str, int (*arr)[COL], int rows ) ) ( char * ) )[COL]
{
    int i, j;
    puts ( str );
    for ( i = 0; i < rows; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%d ", *(*(arr+i)+j) );
        putchar ( '\n' );
    }
    return show;
}

int main ( void )
{
    mydata (*p)[COL];
    int i, j;
    int matrix [][COL] = {{ 1, 2 }, { 3, 4 }};
    func ( "no", matrix, sizeof matrix / sizeof matrix [ 0 ] ) ( "yes" );
    p = ( * func ( "no", matrix, sizeof matrix / sizeof matrix [ 0 ] ) ) ( "yes" );
    for ( i = 0; i < sizeof hello / sizeof hello [ 0 ]; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%s ", (*(hello+i)+j) );
        putchar ( '\n' );
    }
}

усложним mydata ( * ( * func ( char * str, int (*arr)[COL], int rows ) ) ( char *, mydata (*pt)[COL], int rows ) )[COL]; func есть идем вправо функция принимающая символьную строку указатель на массив из COL элементов типа int считай столбцов и количество строк влево идем которая возврщает указатель на идем вправо функцию которая принмает символьную стоку и количество строк и столбцов матрицы идем влево и возвращает указатель на идем вправо массив из COL элементов идем влево типа mydata

#include
#define COL 2
#define SIZE 5

typedef struct _mydata
{
    char my [ SIZE ];
} mydata;

mydata hello [][COL] = {{ "2000", "3000"}, {"4000", "5000" }};

mydata ( * show ( char * str , mydata (*pt)[COL], int rows) )[COL]
{
    int i, j;
    mydata (*g)[COL] = hello;
    for ( i = 0; i < rows; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%s ", (*(pt+i)+j)->my );
        putchar ( '\n' );
    }
    puts ( str );
    return g;
}

mydata ( * ( * func ( char * str, int (*arr)[COL], int rows ) ) ( char *, mydata (*pt)[COL], int rows ) )[COL]
{
    int i, j;
    puts ( str );
    for ( i = 0; i < rows; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%d ", *(*(arr+i)+j) );
        putchar ( '\n' );
    }
    return show;
}

int main ( void )
{
    mydata (*p)[COL];
    mydata arr [][COL] = {{"666", "777" }, { "800", "900" }};
    int i, j;
    int matrix [][COL] = {{ 1, 2 }, { 3, 4 }};
    func ( "no", matrix, sizeof matrix / sizeof matrix [ 0 ] ) ( "yes", arr, sizeof arr / sizeof arr [0 ] );
    p = ( * func ( "no", matrix, sizeof matrix / sizeof matrix [ 0 ] ) ) ( "yes", arr, sizeof arr / sizeof arr [0 ] );
    for ( i = 0; i < sizeof hello / sizeof hello [ 0 ]; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%s ", (*(hello+i)+j)->my );
        putchar ( '\n' );
    }
}

усложним mydata ( * ( * func ( char * str, int (*arr)[COL], int rows, void (*tt) (void) ) ) ( char *, mydata (*pt)[COL], int rows ) )[COL] ; func есть идем вправо функци котора принимает строку матрицу и указатель на функцию которая ничего не принимает и имеет тип void идем влево и возврщает указатель на вправо указатель на функци которая принимает строку и матрицу идем влево и возвращает указатель на идем вправо указатель на массив из COL элементов влево типа mydata

#include
#define COL 2
#define SIZE 5

typedef struct _mydata
{
    char my[SIZE];
} mydata;
mydata hello [][COL] = {{"2000", "3000"}, {"4000", "5000"}} mydata;

(* show(char * str, mydata (*pt)[COL], int rows))[COL]
{
    int i, j;
    mydata (*g)[COL] = hello;
    for ( i = 0; i < rows; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%s ", (*(pt+i)+j)->my );
        putchar ( '\n' );
    }
    puts ( str );
    return g;
}

void tt ( void )
{
    puts ( "tt" );
}
mydata (* (* func (char * str, int (*arr)[COL], int rows, void (*tt) (void))) (char *, mydata (*pt)[COL], int rows))[COL]
{
    int i, j;
    puts ( str );
    tt ( );
    for ( i = 0; i < rows; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%d ", *(*(arr+i)+j) );
        putchar ( '\n' );
    }
    return show;
}

int main ( void )
{
    mydata (*p)[COL];
    mydata arr [][COL] = {{"666", "777" }, { "800", "900" }};
    int i, j;
    int matrix [][COL] = {{ 1, 2 }, { 3, 4 }};
    func ( "no", matrix, sizeof matrix / sizeof matrix [ 0 ], tt ) ( "yes", arr, sizeof arr / sizeof arr [0 ] );
    p = ( * func ( "no", matrix, sizeof matrix / sizeof matrix [ 0 ], tt ) ) ( "yes", arr, sizeof arr / sizeof arr [0 ] );
    for ( i = 0; i < sizeof hello / sizeof hello [ 0 ]; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%s ", (*(hello+i)+j)->my );
        putchar ( '\n' );
    }
}

усложним mydata ( * ( * func ( char * str, int (*arr)[COL], int rows , mydata ( * tt ( mydata (*mas)[COL] ))[COL])) ( char *, mydata (*pt)[COL], int rows ) )[COL]; func есть идем вправо функция которая принимает строку матрицу и указатель на функцию которая принмает матрицу и возвращает массив из COL элементов типа mydata идем влево и возвращает указатель на идем вправо указатель на функцию которая принимает строку и матрицу идем влево и возвращает указатель на идем вправо указатель на массив идем влево на массив типа mydata

#include
#define COL 2
#define SIZE 5

typedef struct _mydata
{
    char my [ SIZE ];
} mydata;
mydata hello [][COL] = {{ "2000", "3000"}, {"4000", "5000" }};
mydata ( * show ( char * str , mydata (*pt)[COL], int rows) )[COL]
{
    int i, j;
    mydata (*g)[COL] = hello;
    for ( i = 0; i < rows; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%s ", (*(pt+i)+j)->my );
        putchar ( '\n' );
    }
    puts ( str );
    return g;
}

mydata ( * tt ( mydata (*mas)[COL] ))[COL]
{
    int i, j;
    static mydata ret [][COL] = {{"7", "8" }, {"9", "10" }};
    for ( i = 0; i < 2; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%s ", (*(mas+i)+j)->my );
        putchar ( '\n' );
    }
    puts ( "tt" );
    return ret;
}

mydata ( * ( * func ( char * str, int (*arr)[COL], int rows , mydata ( * tt ( mydata (*mas)[COL] ))[COL])) ( char *, mydata (*pt)[COL], int rows ) )[COL]
{
    int i, j;
    static mydata ma [][COL] = {{ "1", "2"}, {"3", "4"}};
    mydata (*gk)[COL];
    puts ( str );
    gk = tt ( ma );
    for ( i = 0; i < sizeof *gk / sizeof (*gk)[0]; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%s ", (*(gk+i)+j)->my );
        putchar ( '\n' );
    }
    for ( i = 0; i < rows; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%d ", *(*(arr+i)+j) );
        putchar ( '\n' );
    }
    return show;
}

int main ( void )
{
    mydata (*p)[COL];
    mydata arr [][COL] = {{"666", "777" }, { "800", "900" }};
    int i, j;
    int matrix [][COL] = {{ 1, 2 }, { 3, 4 }};
    func ( "no", matrix, sizeof matrix / sizeof matrix [ 0 ], tt ) ( "yes", arr, sizeof arr / sizeof arr [0 ] );
    p = ( * func ( "no", matrix, sizeof matrix / sizeof matrix [ 0 ], tt ) ) ( "yes", arr, sizeof arr / sizeof arr [0 ] );
    for ( i = 0; i < sizeof hello / sizeof hello [ 0 ]; i++ )
    {
        for ( j = 0; j < COL; j++ )
            printf ( "%s ", (*(hello+i)+j)->my );
        putchar ( '\n' );
    }
}

итак можно усложнять до бесконечности главное понять как читать правильно описание но это может сыграть с вами злую шутку каждый раз открывая свой исходник вам будет тяжело держать в голове все эти сложные типы и вместо удовольствия будет голова болеть распутывая эти описания надо стремится писать самый простой код оценил задачу выбрал самый простой алгоритм какой только возможно и потом только написал чтоб все было на уровне новичка по сложности но эффективно тогда никакой головной боли не будет все будет как на ладони это конечно если не надо оптимизировать тогда придется смирится что чем эффективней алгоритм тем больше кода и разных моментов придется в голове держать кучу но если никто не требует оптимизации пишите самый простой код какой только возможно.Удачи.

twitter.com facebook.com vkontakte.ru odnoklassniki.ru mail.ru yandex.ru

При цитировании, копировании, клонировании материалов с сайта целиком или частично, ссылка на страницу, откуда был скопирован материал, обязательна! При нарушении данных условий прошу незамедлительно удалить со своих ресурсов скопированный материал. Администрация сайта.



Комментариев: 0

    Оставьте комментарий!

    grin LOL cheese smile wink smirk rolleyes confused surprised big surprise tongue laugh tongue rolleye tongue wink raspberry blank stare long face ohh grrr gulp oh oh downer red face sick shut eye hmmm mad angry zipper kiss shock cool smile cool smirk cool grin cool hmm cool mad cool cheese vampire snake excaim question

    Используйте нормальные имена

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

    (обязательно)