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

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

даже веб интерфейс есть https://cdecl.org

На вот это

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

он пишет: "syntax error" :)

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


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

так уж получилось что func здесь зарезервированное слово

 

cdecl> explain char(*(*fffff(void))[3])(void)

declare fffff as function (void) returning pointer to array 3 of pointer to function (void) returning char

 

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


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

declare fffff as function (void) returning pointer to array 3 of pointer to function (void) returning char

Хрен редьки не слаще:)

 

ЗЫ. Спасибо за инфу о cdecl, не знал.

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


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

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

void f1(void);

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

Ну да, f1 не функция, а имя функции. Значением f1 является адрес функции. Две записи абсолютно одинаковы:

void (*v1)(void) = f1;
void (*v2)(void) = &f1;

Для адреса функции оператор () выполняет вызов соответствующей функции. Т.е. вызов функции по известному адресу можно сделать так:

(void (*)(int)) 0x1000 (5);

 

Илья

Изменено пользователем 501-q

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


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

Удобно для расшифровки выражение подобных char (*(*func(void))[3])(void); пользоваться The "Clockwise/Spiral Rule''

 

Я в голове ещё держу - "Начало отсчёта "12:00" - начало суток, и в нормальном течении времени..."

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

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


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

const int a = 10;


void f()
{
  int *y;
  y = (int*)&a;
  y = 12;
  ....
 }

встретил такой код. работает. Тут все в порядке? 

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


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

4 минуты назад, razrab83 сказал:

встретил такой код. работает. Тут все в порядке? 

На этом y=12 компилятор должен ругнуться.

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


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

8 минут назад, jcxz сказал:

На этом y=12 компилятор должен ругнуться.

сорри.... опечатался

const int a = 10;


void f()
{
  int *y;
  y = (int*)&a;
  *y = 12;
  ....
 }
Изменено пользователем razrab83

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


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

Здесь всё нормально. А что смущает?

Нормально для компилятора. При выполнении возможно будет сбой - смотря в какой памяти расположена a.

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


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

вот это меня и смущает. этот код компилится и работает. и кочует из проекта в проект. на этом камне с этим компилятором всё нормально. а в другом окружении "выстрел в ногу".  Или я загоняюсь и при любом раскладе все будет работать?

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


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

1 час назад, razrab83 сказал:

Или я загоняюсь и при любом раскладе все будет работать?

Нет, при любом раскладе не обязан. Объявленная с квалификатором const переменная a может оказаться в доступной только для чтения памяти (или флеш или защищенная MMU область памяти) и выполнение присваивания по этому адресу вызовет нештатную ситуацию. А раз вы решились задать этот вопрос - вы, наверняка, и сами это понимаете. А явное приведение типа - это решение программиста: либо он хорошо знает, что делает, либо стреляет себе в ногу.

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


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

10 часов назад, razrab83 сказал:

Тут все в порядке? 

Синтаксически да. А логически нет. 

Чтгбы всё было в порядке, не надо работать в функции с глобальными переменными. Если их надо менять - передавайте в функцию указатель на неё, и работайте с ним.

Скрытый текст

 


const int a = 10;

void SetArg(int *y, int NewVal)
{
  ...
  *y = NewVal;
  ....
 } 

// Применение

SetArg(&a, 12);

В этом случае компилятор отследит изменение значения константы по указателю на неё при вызове функции. При const int a он выдаст ошибку. А при int a нет.

 

 

 

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

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


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

46 минут назад, Darth Vader сказал:

Синтаксически да. А логически нет. 

Чтгбы всё было в порядке, не надо работать в функции с глобальными переменными. Если их надо менять - передавайте в функцию указатель на неё, и работайте с ним.

  Скрыть содержимое

 



const int a = 10;

void SetArg(int *y, int NewVal)
{
  ...
  *y = NewVal;
  ....
 } 

// Применение

SetArg(&a, 12);

В этом случае компилятор отследит изменение значения константы по указателю на неё при вызове функции. При const int a он выдаст ошибку. А при int a нет.

 

 

 

 

не я автор кода. я бы всё в ++ увел. тут пуре си. на си сделано что-то типа ооп. и сделано все чуть менее чем полностью на глобальных переменных (раньше так писали, это было нормально). я бы сам так делать не стал.

а по поводу вашего примера SetArg(&a, 12);.... так тут почти так и есть... ошибку дает компилятор, поэтому автор делает так SetArg((int *)&a, 12); Т.е. объявляет константную структуру, а потом где-то пытается её модифицировать. Компилятор ругается. В этом месте стоит явное приведение к типу без конст. 

 

Я уже принял меры и выправил этот код. Просто перед правкой решил убедиться, что мои опасения не напрасны.

Всем спасибо.

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


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

14 часов назад, razrab83 сказал:

ошибку дает компилятор, поэтому автор делает так SetArg((int *)&a, 12); Т.е. объявляет константную структуру, а потом где-то пытается её модифицировать. Компилятор ругается. В этом месте стоит явное приведение к типу без конст.

Остается открытым вопрос, зачем изначально делать структуру константной, если знаешь, что где-то будешь её модифицировать? И ради этого придется городить костыли с явным приведением типа для снятия константности...  Не могу найти рационального объяснения такого антипаттерна.

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


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

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

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

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

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

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

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

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

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

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