LINUX.ORG.RU

Использование «стража» вместо sizeof на массивах

 ,


1

2

Здравствуйте.

Читаю «Programming In Lua». В главе про C API автор постоянно заканчивает массивы структур «стражем» - структурой с нулевыми полями. Видимо для того, чтобы в цикле можно было проверить, что структура последняя.

Мне не понятно, почему используется такой «изобретательный» подход вместо sizeof?

      struct ColorTable {
        char *name;
        unsigned char red, green, blue;
      } colortable[] = {
        {"WHITE",   MAX_COLOR, MAX_COLOR, MAX_COLOR},
        {"RED",     MAX_COLOR,         0,         0},
        {"GREEN",           0, MAX_COLOR,         0},
        {"BLUE",            0,         0, MAX_COLOR},
        other colors
        {NULL, 0, 0, 0}  /* sentinel */
      };
★★★★★

Последнее исправление: makoven (всего исправлений: 1)
Ответ на: комментарий от Stil

если я пишу на С++, то да, благо есть средства на любой вкус — и константы, и инлайн функции, и constexpr, и шаблоны... на С++ не помню, чтобы писал дефайны.

но сишка-то убога. там ничего этого нет, там дефайн, нередко — самое красивое решение, да и не так опасны они, как часто толкуют. вот как, например, на Си вы сделаете банальную константу, если const компилятор полноценно не поддерживает (выделяет под const int smth; память)?

next_time ★★★★★
()
Ответ на: комментарий от Eddy_Em

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

next_time ★★★★★
()
Ответ на: комментарий от next_time

ну если так судить, то конечно. у разрабов плюсов видать Си ГМ поголовно...

у разрабов плюсов наблюдается полное отсутствие мозга, а еще границ и стен

...а ещё у разрабов Qt тоже видать Си ГМ...

qt написан на си?

unt1tled ★★★★
()
Последнее исправление: unt1tled (всего исправлений: 1)
Ответ на: комментарий от unt1tled

qt написан на си?

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

next_time ★★★★★
()
Ответ на: комментарий от beastie

А во вторых, ты вычисляешь размер при каждой итерации for.

Скорее всего в релизе там будет константа, но я инициализирую явно:

for(size_t i = 0, size = calc_size(..); i < size; i++) { }

andreyu ★★★★★
()
Ответ на: комментарий от next_time

если const компилятор полноценно не поддерживает

Нет таких компиляторов.

А С++ — дерьмо. Сишечка божественна.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Сишечка божественна.

Может и так, но у меня, почему-то занимает неделю выучить какое-нибуль api под нее. Будь то sqlite или jansson или работу с tty. Поэтому буду писать на луа, а системные вещи оформлять в виде луа-модулей)

makoven ★★★★★
() автор топика

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

true_admin ★★★★★
()
Ответ на: комментарий от makoven

А я считаю, что лучше день потерять, а потом за полчаса долететь! И даже "скрипты" на сях пишу! Правда, это еще оттого, что я очень плохо знаю баш, а из ЯП признаю только С и больше ничего не знаю (хотя, С я тоже хреново знаю).

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от true_admin

писать на пистоне, а системные вещи оформлять с помощью cffi

Отрецензировал фикс фикса.

Deleted
()
Ответ на: комментарий от Deleted

Да, надо было изначально брать питон. Но уже лень переходить. К тому же в будущем предпологается встроить lua в проект в качестве dsl, чтобы можно было из браузера написать сценарий для какой-нибудь люстры.

makoven ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Во, так проще. Видать в c89 так делать было нельзя поэтому автор писал полностью

makoven ★★★★★
() автор топика
Последнее исправление: makoven (всего исправлений: 1)
Ответ на: комментарий от makoven

Думаю что в общем случае не прокатит. Например, если речь идёт о массиве структур (array of structures) то ты не можешь её заменить указателем. Буду рад ошибаться.

true_admin ★★★★★
()
Ответ на: комментарий от makoven

Жабоскрипт не считается ЯПом, т.к. говно. Там ни типов переменных не задашь, ни структур данных, ни с блобами напрямую не поработаешь... Ублюдок от жабки, одним словом.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от anonymous

{0} инициализирует все как надо, не важно что там и сколько уровней вложенности.

Вообще это не совсем так. Всё будет инициализировано как надо только в том случае, если значение первого элемента представимо в виде числа. Если же первый элемент - структура, то компилятор будет ругаться. GCC в качестве расширения допускает инициализацию, состоящую из пустых скобок - {}, тогда точно не важно, что там внутри. Если же следовать стандарту, то, наверное, лучше инициализировать так: {.any_integral_var = 0}, но в качестве переменной выбирать такую, которая с меньшей вероятностью может быть переименована в будущем.

Sorcerer ★★★★★
()
Ответ на: комментарий от next_time

на самом деле, вспомните С-строки. классический пример, когда такое действительно удобно: получаем экономию памяти, причём, возможно, весьма существенную, т.к. строк может много и они могут сравнимой с int длины, строки часто приходится перебирать от начала до конца, поэтому накладные расходы на получение размера — небольшие.

Боже, упаси нас от такой экономии.

LongLiveUbuntu ★★★★★
()
Ответ на: комментарий от Eddy_Em

Сишечка божественна.

чем?

А С++ — дерьмо.

только вот на С++ я могу, вместо того чтобы создавать 100-байтную нулевую структуру, взять стандартный шаблон вектор и иметь с любыми структурами/классами меньше накладных расходов, чем вы на своей сишечке, при большем удобстве вектора.

next_time ★★★★★
()
Ответ на: комментарий от next_time

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

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

ненадо только говножс к солнцеликой жабе приплетать

unt1tled ★★★★
()
Ответ на: комментарий от Eddy_Em

откуда он свистеть и тормозить будет, если это шаблон, который работает на этапе компиляции и все методы его определены как подставляемые (их вызов тоже работает на стадии компиляции)?

накладные расходы на обращение к элементу — нулевые, и уж всяко ниже, чем при таком вот подходе, как у вас, с созданием нулевой структуры.

next_time ★★★★★
()
Ответ на: комментарий от Eddy_Em

Так в си тоже не всё хорошо с типизацией и памятью. Когда пишешь, есть чувство, что ходишь по лезвию бритвы) Rust тебе наверное понравится - вот там всё железно

makoven ★★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

ага: «The calloc() function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to the allocated memory. The memory is set to zero.»

она весь массив зануляет, это ещё куча накладных расходов, нет, спасибо.

next_time ★★★★★
()
Ответ на: комментарий от Eddy_Em

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

next_time ★★★★★
()
Ответ на: комментарий от next_time

она весь массив зануляет, это ещё куча накладных расходов, нет, спасибо

Ну так выбирай сам: либо сразу занулить, либо позже, но есть шанс забыть. Я обычно для создаваемых пустых структур именно calloc использую: все поля автоматом нулевые → заполнять нужно лишь то, что нужно.

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

Ну ты и шутник... Что может быть хуже говнокомпилятора от мелкомягких? Вообще, говорят, что icc наиболее качественно оптимизируемый код генерирует. Но как-то огорожен он... Лучше уж gcc (ну или шланг — на любителя).

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Ну так выбирай сам: либо сразу занулить, либо позже, но есть шанс забыть. Я обычно для создаваемых пустых структур именно calloc использую: все поля автоматом нулевые → заполнять нужно лишь то, что нужно.

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

Ну ты и шутник... Что может быть хуже говнокомпилятора от мелкомягких?

я про keil спрашиваю. мелкомягкий компилер - известное говно.

next_time ★★★★★
()
Ответ на: комментарий от next_time

я про keil спрашиваю

Так и хочется похаять говнопроприетарщину, но не буду. Т.к. вообще не в курсе, что там.

Я-то под микроконтроллеры gcc использую (для 32-битных) или sdcc (для 8-битных). Правда, sdcc еще сильно недопилен, но лучше уж хоть как-то, чем вообще никак!

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Правда, sdcc еще сильно недопилен, но лучше уж хоть как-то, чем вообще никак!

о том и речь. писать на сыром компиляторе под железо - ССЗБ.

next_time ★★★★★
()
Ответ на: комментарий от beastie

Первый вариант на мой взгляд лучше оптимизируется в compile-time, второй более универсален. А использовать можно оба по ситуации.

Dark_SavanT ★★★★★
()
Ответ на: комментарий от anonymous

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119

По ссылке говорится о {0} как об универсальном инициализаторе для Си, который якобы специально описан в стандарте, но подтверждения этих слов я не нахожу (см. 6.7.9 Initialization). Может, вы мне покажете?

Sorcerer ★★★★★
()
Ответ на: комментарий от next_time

В ядре это называется ARRAY_SIZE и используется на статических массивах.

Dark_SavanT ★★★★★
()
Ответ на: комментарий от Sorcerer

Вот пункт, который явно разрешает не ставить скобки:

20 If the aggregate or union contains elements or members that are aggregates or unions, these rules apply recursively to the subaggregates or contained unions. If the initializer of a subaggregate or contained union begins with a left brace, the initializers enclosed by that brace and its matching right brace initialize the elements or members of the subaggregate or the contained union. Otherwise, only enough initializers from the list are taken to account for the elements or members of the subaggregate or the first member of the contained union; any remaining initializers are left to initialize the next element or member of the aggregate of which the current subaggregate or contained union is a part.

anonymous
()

не работает при ошибке больше чем на 1

anonymous
()
Ответ на: комментарий от anonymous

Да, согласен. {0} должно работать. Но только пока что предупреждения сыплет. И есть нюансы (неоднозначности) для кода, использующего расширения gcc - пустые структуры или структуры с единственным элементом - массивом из 0 элементов.

Sorcerer ★★★★★
()

ещё одна гипотеза- концепция координат(из-за политических причин больше известных под названием итераторов)

«нулевой» объект вариант выхода координаты за пределы полуоткрытого отрезка [start,end)

sizeof же больше подходит для концепции целого , а не последовательности.

зы. Хоара то структуры то полистал а?

qulinxao ★★☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.