Перейти к содержанию
    

модификатор const. Как правильно использовать в Си

Мудреные конструкции наподобие вышеприведенных разбираются в учебнике K&R "Язык C", там и метод описан. В жизни мне использовать нет необходимости.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

P.S. func - это функция, не принимающая аргументов и возвращающая указатель на массив указателей на функции, которые возвращают char и не принимают параметров.

func - не функция, а указатель на функцию.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

+++! А какой у них при этом умный вид! Как правило это всякие КТН, с напускным видом умудренного опытом жирного кота. Если посмотреть потом их код - как правило это академическая муть с неочевидной перегрузкой операторов, неуклюжей попыткой засунуть ООП там, где оно вообще не надо итп. Реально полезного - ноль, собственно поэтому и ищут людей ))

 

Стоит заметить, что ваши личные комплексы не являются темой данного обсуждения. Если у вас есть какие-то жизненные упущения, как то неполученный статус КТН, например, можете завести отдельную тему, где поплачитесь, а мы вас подбодрим добрым словом.

 

:biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"поплачИтесь" ,- непременно

 

func - не функция, а указатель на функцию.

Совсем ничего не соображаю, а почему такая запись возможно тогда?

char(*(*func(void))[3])(void)
{	
char(*(*f)[3]) (void) = NULL;	
return f;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

func - не функция, а указатель на функцию.

Вы не правы.

 

Совсем ничего не соображаю, а почему такая запись возможно тогда?

CODE

char(*(*func(void))[3])(void)

{

char(*(*f)[3]) (void) = NULL;

return f;

}

Потому что func - это то, что я писал выше. А вот f - это указатель на массив указателей на функции. Записи логически и синтаксически корректны.

Изменено пользователем Arlleex

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"поплачИтесь" ,- непременно

 

Ваше замечание притянуто за уши. Поскольку Я применяю это слово редко (или не применяю вовсе), могу делать в нем столько ошибок, сколько захочу. Я же не яйцеголовый КТН в самом деле! И если меня кто-то на собеседовании поправит, обязательно настучу по голове, как было предложено выше.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

логически и синтаксически корректны.

жаль что совершенно нечитаемы (мне). Всегда удивляют (приятно) люди (на Хабре например) которые это щелкают как орехи. Не понимаю, как при обычном программировании можно получить опыт чтения такого.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы не правы.

char (*(*func(void))[3])(void);

 

да, не указатель (проглядел скобки справа), но это и не функция. :) Строго говоря, func - есть имя функции, которое семантически является её адресом, т.е. технически это указатель. Всё выражение да, не указатель, но, строго, и не функция.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

P.S. func - это функция, не принимающая аргументов и возвращающая указатель на массив указателей на функции, которые возвращают char и не принимают параметров.

 

Припомнил у себя в проекте такой же код, правда только после того, как вы на русском дали разъяснение по своему примеру. Там все было сделано через typedef и по сути даже более сложная структура была.

 

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

 

typedef int32_t /*successful = 0*/ ( *callback_func_t ) ( uint32_t /*protocol status*/ );

typedef callback_func_t callback_tbl_t[LAST_CALLBACK_ID];

typedef struct { 
    uint32_t id; 
    callback_tbl_t cl_tbl;  
} proto_impl_t;

static proto_impl_t impl[MAX_NOF_IMPLS] = { 0 };

callback_tbl_t *impl_get_callbacks ( uint32_t impl_id ) {

    for ( uint32_t i = 0; i < MAX_NOF_IMPLS; i++ ) {
        if ( impl[i].id == impl_id ) {
            return &impl[i].cl_tbl;
        }
    }

    int32_t ( *(*f)[32] ) (uint32_t) = NULL;    /* Это я уже сейчас добавил, проверить ругнется ли компилятор. Не ругается. */

    return f;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

char (*(*func(void))[3])(void);

 

да, не указатель (проглядел скобки справа), но это и не функция. :) Строго говоря, func - есть имя функции, которое семантически является её адресом, т.е. технически это указатель. Всё выражение да, не указатель, но, строго, и не функция.

Технически любое имя функции - это есть указатель. Даже

void f1(void);

Согласно Вашей логике, f1 - не функция? Стандартописатели из комитета ANSI C ошиблись с терминологией? :rolleyes:

Все выражение, все-таки - функция... Вернее, ее прототип.

char (*(*func(void))[3])(void)
{
  ...
}

Технически, синтаксически, логически, семантически (что там еще?) - это именно функция. Я могу ее вызвать, потому что это функция. Я не могу присвоить func ничего, потму что это не указатель, а идентификатор, связанный с выделенным участком кода.

 

Вот небольшой пример

// ôóíêöèÿ, âîçâðàùàþùàÿ óêàçàòåëü íà ìàññèâ óêàçàòåëåé íà ôóíêöèè, âîçâðàùàþùèå char 

#include <stdio.h> 

char func1(void) {printf("I am func1\n"); return 1;} 
char func2(void) {printf("I am func2\n"); return 2;} 
char func3(void) {printf("I am func3\n"); return 3;} 

char (*MassFunc[3])(void) = {func1, func2, func3}; 

char (*(*func(void))[3])(void) 
{ 
    return &MassFunc; 
} 

int main(void) 
{ 
    int *pFunc = (int *)func(); 
    
    for(int i = 0; i < 3; ++i) 
       (*(char (*)())pFunc[i])(); // в С указатели на функции не индексируются, поэтому используется промежуточный указатель на int
    
    while(1); 
}

image.png

 

Важное замечание №1: если все-таки придется использовать какую-то гибкую схему вызовов - лучше, как и было озвучено Quasar, через typedef.

Важное замечание №2: не пишите так никогда (как в примере выше у меня). Это всего лишь пример, но никак не побуждение к действиям. Если и хочется сделать что-то гибко и структурно - лучше тщательно продумать концепцию кода и оформить с typedef-ами (иначе Вас потом будут проклинать :biggrin: ).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"в С указатели на функции не индексируются," - о как, даж не знал

А недавно узнал для чего были ссылки в ++ сделаны - именно потому, что иначе была бы невозможна перегрузка некоторых операторов для объектов без конфликта с семантикой С, она уже задействована под арифметикой указателей. А не всякие там пояснения что мол для безопасности, типа ссылку нельзя неинициализированной и все такое (кстати в гугл используют указатели в явном виде (ну когда на ++ пишут)).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

char (*(*func(void))[3])(void);

1 : 1 копия примера из K&R, на трезвую голову такого не придумать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

char (*(*func(void))[3])(void);

1 : 1 копия примера из K&R, на трезвую голову такого не придумать.

K&R прочел совсем немного, к сожалению, и не знал, что у них вообще затрагивается эта тема :laughing:

Пример действительно из головы.

Ведь можно и еще больше усложнить...

P.S. Посмотрел в K&R - действительно, есть такой пример :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если вам так нравится разбирать сложные декларации, cdecl существует уже лет как 20, даже веб интерфейс есть https://cdecl.org

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...