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

(Не)доработки языков программирования

Хотел красиво оптимизировать Си-код, выполняющий общие действия для сложносоставного условия-алгоритма, содержащего в себе вызов void-функций между несколькими булевыми выражениями внутри if-условия. Чтобы обходиться без goto или дублирования исполняемого выражения (тела) if.

void foo1(int);
...

void foo2(void);
...


int main()
{
    .....
    if (expr1) goto do_foo2;
    foo1(a);
    if (expr2) {
    do_foo2:
        foo2();
    }
    .....
}

 

Получилось так

{
    if (expr1 || (foo1(a), expr2)) {
        foo2();
    }
}

 

Но понял, что разработчик неудачно выбрал оператор/символ для функции Comma. Удачнее было бы нагрузить двоеточие этой функцией. А запятая оставалась бы только разделителем множества элементов. С двоеточием появились бы новые плюшки. Например, внутри первого выражения в for в режиме C99 можно было бы создавать несколько разнотипных переменных. И некрасивое do {....} while(0) в дефайнах не понадобилось бы, т.к. двоеточием можно было бы "склеить" несколько независимых выражений/действий, выполняющихся строго вместе. И, если пофантазировать, то в режиме C2100 можно было бы создавать (локальные) переменные внутри многих мест, где пока это запрещено. Например внутри условных выражений if, while, прочих, с ограничением области видимости переменной только внутри границ ключевого слова (if, while,...).

 

И ещё, касательно unions. Бросается в глаза удобство варианта, когда при описании членов union, массив, а так же список однотипных членов, разделённых запятой, делаются по логике создания структуры. То есть это будут члены/переменные, следующие в адресном пространстве друг за другом. И только после точки с запятой адрес следущего члена обнуляется.

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

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


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

Единственное, что я пользовал в Pascal, а в С этого нет - так это вложенные процедуры.

 

в GNU-C это есть где-то с 1999 года, ужасно удобно, так как пространство имен вспомогательных вложенных функций и вспомогательных переменных не засоряется, но в ISO стандарт так и не попало, посему GNU поддерживает это на общественных началах, и, как я понимаю, не на всех архитектурах.

 

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

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


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

:bb-offtopic:

что де пиши на С++, но там аналогичный код становится достаточно большим,
Нда, шел 2017год, а наш народ по прежнему рассказывал, как на с++ код становится достаточно большим..... Грустно :(

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


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

Хотел красиво оптимизировать Си-код,

    if (expr1) goto do_foo2;
    foo1(a);
    if (expr2) {
    do_foo2:
        foo2();
    }
    
}

 

Получилось так

{
    if (expr1 || (foo1(a), expr2)) {
        foo2();
    }
}

Нда, уж, афигеть, оптимизация.

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

 

if ( ! expr1 )
    foo1();
if ( expr1 || expr2 )
    foo2();

 

Зачем мудрить-то?

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


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

в GNU-C это есть где-то с 1999 года

В gcc5 это посчитали вредным, поэтому в опции компилятора теперь нужно добавлять -Wno-trampoline, иначе не соберется (я всегда указываю -Wall -Wextra, чтобы не было соблазна игнорировать предупреждения).

А вот что мне не нравится, так это работа с сокетами! Ну никак не обойтись без таймаутов...

Изменено пользователем Эдди

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


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

В gcc5 это посчитали вредным, поэтому в опции компилятора теперь нужно добавлять -Wno-trampoline, иначе не соберется (я всегда указываю -Wall -Wextra, чтобы не было соблазна игнорировать предупреждения).

А вот что мне не нравится, так это работа с сокетами! Ну никак не обойтись без таймаутов...

socket ы это библиотека а не язык....

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


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

Вообще-то, сокеты входят в stdlib — для работы с ними дополнительных библиотек линковать не надо.

Но сама по себе реализация как-то не очень… Скажем, если write в закрытый сокет вернет ошибку, то read вернет просто 0 — как будто бы данных нет! И select/poll с закрытым сокетом ошибку не дадут.

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


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

Вообще-то, сокеты входят в stdlib — для работы с ними дополнительных библиотек линковать не надо.

Ну, дык, это всё равно же библиотека. Причем реализаций этой библиотеки довольно много.

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


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

Предлагаю не рассматривать всякие альтернативы. Обычный "стандартный" gcc и stdlib. Дома я еще на 4.9.3 сижу, на работе давно уже на 5.4.0 перешел.

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


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

Предлагаю не рассматривать всякие альтернативы. Обычный "стандартный" gcc и stdlib.

Вы б с содержимым стандартов для начала ознакомились. Не входят сокеты в стандартную библиотеку С99/11. C++ я не знаю, но поиском по pdf С++2014 ничего похожего на сокеты тоже не нашел.

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


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

Гость TSlicer
Вы бы с содержимым стандартов для начала ознакомились.

В горах - все по другому. Там звезды ближе и телескопы есть.

 

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


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

Скажем, если write в закрытый сокет вернет ошибку, то read вернет просто 0 — как будто бы данных нет!

Ну не знаю, как у Вас, а у меня 0, полученный от read() для сокета однозначно идентифицирует, что он был закрыт с другой стороны.

Вот если удалённый хост упал - да, вы будете ждать некоторое время, пока стек решит, что связи больше не будет, но это решается, например, уровнем выше :)

 

А вообще, вот очень хороший материал:

Снейдер Йон: Эффективное программирование TCP/IP.

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


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

Продолжаем фантазировать.

Надо что-то вроде инкомплит-тайп-каст'а. Чтобы сделать "принудительное" чтение переменной типа result = *(volatile *)&var; которая объявлена конечно же неволатильной. Скажете: сделай сразу переменную волатильной. А я отвечу: хочу массив неволатильных переменных, а первый элемент волатильный))) Ну и для всяческих приблуд pack/align/const.

 

Хотя инкомплит неудачное название. Лучше что-то вроде "атрибут-тайп-каст". Понятно, что что-то похожее можно сделать через стандартный тайп-каст, но хочется чтобы это работало без явного указания ширины переменной, вобщем лишней инфы. И из этой же оперы, хотелось делать тайп-каст (signed) или (unsigned). Это уже инкомплит-тип.

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

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


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

1. Было-бы лучше, если бы в си, при объявлении инициализированного массива с явно указанной размерностью

int m[N] = {1, 2, 3};

компилятор выдавал бы ошибку компиляции если количество инициализаторов не равно N.

Это очень полезно для создания связанных списков: define_значение/значение_константы.

2. Было бы очень полезно, если бы в константных выражениях можно было смешивать строки и значения:

enum {z1 = 5};

char const t[] = "string" z1 " - " (z1+2)*9;

3. Было бы классно если бы строковые константы можно было задавать не только в форме ASCIIZ (завершающийся нулём набор символов), но и в виде:

длина_строки "строка" (без 0 в конце). Хотя это решается автоматически при выполнении пункта 2.

4. Полезно было бы в stdlib в обязательном порядке внести прототип функции _Printf(void *(*)(void *), void *, char *, ...) - т.е. функцию из семейства printf...() передающую поток выводимых символов не на stdout (printf()) или в память (sprintf()), а в callback-функцию (первый аргумент _Printf()).

5. Было бы очень полезно наличие в языке возможностей задания списков define-ов (или enum) с уникальными значениями. Т.е. чтобы на:

enum {V_1 = 11, V_2 = 12, V_3 = 13, V_4 = 11, ...};

вылетало на ошибке компиляции типа: "V_4 - duplicate value".

Часто приходится задавать или списки define ног контроллера или каналов DMA, портов и пр. ресурсов, в которых каждый элемент списка должен иметь уникальное значение, не совпадающее с другими. При каждом редактировании очень неудобно каждый раз перепроверять весь список на наличие конфликтов, особенно если значения справа от "=" - это не литеральные константы, а выражения.

Приходится выкручиваться через проверяющие макросы.

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


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

1. Было-бы лучше, если бы в си, при объявлении инициализированного массива с явно указанной размерностью

int m[N] = {1, 2, 3};

компилятор выдавал бы ошибку компиляции если количество инициализаторов не равно N.

Да, либо сделать эту опцию управлемой ключом.

enum {V_1 = 11, V_2 = 12, V_3 = 13, V_4 = 11, ...};

вылетало на ошибке компиляции типа: "V_4 - duplicate value".

И здесь согласен. Можно также ключом.

 

Теперь вопрос, кому позвонить. чтобы добавили в IAR 8.22)()))

 

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


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

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

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

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

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

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

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

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

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

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