dil: (Default)
dil ([personal profile] dil) wrote2010-08-02 11:46 am

Никогда не заглядывай в пирожок…

struct uniqueEPGKey
{
        int sid, onid, tsid;
...
        bool operator==(const uniqueEPGKey &a) const
        {
                return !memcmp( &sid, &a.sid, sizeof(int)*3);
        }

Молодцы, блин. Сэкономили полстрочки кода.

Upd: “м-мать”, — звонко откликнулось эхо.

unsigned int magic=0;
fread( &magic, sizeof(int), 1, f);
if (magic != 0x98765432)
{
        eDebug("[EPGC] epg file has incorrect byte order.. dont read it");
        fclose(f);
        return;
}

Оригинал этой записи. Комментировать можно тут или там.

Любые материалы из этого блога запрещается использовать на сайте livejournal.ru в любой форме и любом объёме

[identity profile] dil.livejournal.com 2010-08-02 11:10 am (UTC)(link)
Не, оно даже будет работать. Обычно. А когда-нибудь потом сломается..

[identity profile] blacklion.livejournal.com 2010-08-02 11:12 am (UTC)(link)
Не на x86 каком-нибудь.

[identity profile] dil.livejournal.com 2010-08-02 11:15 am (UTC)(link)
Архитектура тут, скорее всего, ни при чём. У меня сейчас на мипсе работает. Это если когда-нибудь выравнивание случится не по границе int'а. Это редкость, но бывает.

[identity profile] klopp.livejournal.com 2010-08-04 04:49 am (UTC)(link)
А что, оптимизаторы нынче настолько умные, что смотрят так далеко вперёд? Уже давно в потроха сишных не заглядывал, но в [x86 точно] одна из переменных может и в регистре оказаться, например :) Тем более что в memcmp две последних никак не упомянуты.

[identity profile] http://users.livejournal.com/_windwalker_/ 2010-08-02 12:00 pm (UTC)(link)
А у инта в c-ях строго фиксированный размер ?

[identity profile] dil.livejournal.com 2010-08-02 12:03 pm (UTC)(link)
Нет. Зависит от архитектуры и иногда от компилятора и его ключей.
Это C++, хотя в данном случае это не принципиально.

[identity profile] http://users.livejournal.com/_windwalker_/ 2010-08-02 12:09 pm (UTC)(link)
ну мне кажется если magic проверяется то в зависимости от размера int'а могут быть нюансы :/

Но я с ц имел дело в последний раз в универе, так что могу и ошибаться...

[identity profile] dil.livejournal.com 2010-08-02 12:17 pm (UTC)(link)
В зависимости от размера int нюансов не будет, при его изменении поменяется и sizeof(int). А вот при изменении выравнивания этих int'ов в составе struct может наступить жопа. Если, например, они будут 32-битовыми, а выравниваться будут по границе 64-битовых слов.

[identity profile] http://users.livejournal.com/_windwalker_/ 2010-08-02 12:19 pm (UTC)(link)
спасибо, очень толковое объяснение.
ext_659502: (Default)

[identity profile] some41.livejournal.com 2010-08-02 08:53 pm (UTC)(link)
> Если, например, они будут 32-битовыми, а выравниваться будут по границе 64-битовых слов.
как тогда будет выглядеть массив int-ов? в массиве все элементы расположены друг за другом, на расстоянии, равном размеру элемента. поэтому alignment > size у типов данных не бывает (в gcc атрибутами можно поставить что угодно, но массив из такого типа не получится).

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

[identity profile] dil.livejournal.com 2010-08-02 09:10 pm (UTC)(link)
это не массив, это три отдельных int'а

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

понадобиться может, например, для ускорения работы в 64-битовом режиме процессора с 32-битовыми int'ами. хотя ситуация гипотетическая, ятакого тоже ни разу не видел, но всё равно не понимаю, зачем раскладывать себе потенциальные грабли. Трудно было явно сравнить три int'а что ли?
ext_659502: (Default)

[identity profile] some41.livejournal.com 2010-08-02 10:12 pm (UTC)(link)
> это из чего следует?
из стандарта. по определению
An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type.
С++ в этом месте совместим с С.
ну и вообще, нету другого выбора -- до С99 единственный способ сделать массив динамической длины это malloc(sizeof(T)*n). в С++ есть new T[n], но malloc тоже поддерживается.

> понадобиться может, например, для ускорения работы в 64-битовом режиме процессора с 32-битовыми int'ами.
не верю. даже если предположить, что у нас нет операции загрузки 32-ух битного слова (если есть, то и говорить не о чем), то добавлять один шифт на 32 для нечетных слов будет дешевле, чем переводить кэш и шину загрузку мусора.

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

в общем, как ни криво написано, в реальной жизни очень маленькая вероятность сломаться.

[identity profile] dil.livejournal.com 2010-08-03 06:43 am (UTC)(link)
а для чего тогда вообще придумали выравнивание данных по границе слова, если операции загрузки отдельных байтов всё равно всегда были?
ext_659502: (Default)

[identity profile] some41.livejournal.com 2010-08-03 07:50 pm (UTC)(link)
каких данных? выравнивать 8-битные данные на 64-бита вроде еще не придумывали.

обычно выравнивают по 2 причинам 1) данные размера N удобно грузить, когда они выравнены на N 2) для лучшего расположения в кэше; в частности, если грузить не выровненные данные, load может пересечь границу cache line, что неприятно.

ни 1) ни 2) выравнивание 32-бит на 64 в структуре не требуют.

[identity profile] dil.livejournal.com 2010-08-03 06:47 am (UTC)(link)
впрочем, это всё о массивах. а тут три отдельных int'а, хоть и в составе структуры.
ext_659502: (Default)

[identity profile] some41.livejournal.com 2010-08-03 07:52 pm (UTC)(link)
так я и не спорю, что это нарушение стандарта. я говорю, что в реальной жизни не сломается. и это плохо -- уменьшает шансы автора получить по шее.
ext_659502: (Default)

[identity profile] some41.livejournal.com 2010-08-02 08:49 pm (UTC)(link)
первое выглядит, конечно, плохо, но работать будет всегда.
второе не будет работать, если int не 32 бита.

[identity profile] dil.livejournal.com 2010-08-02 09:04 pm (UTC)(link)
более того, оно зачем-то завязано на endianness, хотя этого легко можно было избежать
ext_659502: (Default)

[identity profile] some41.livejournal.com 2010-08-02 09:10 pm (UTC)(link)
из следующего поста у меня сложилось ощущение, что файл пишется строго на той же машине, на которой и читается. тогда endianness не очень важна. вообще, если перестать придираться, то, вполне возможно, и int не 32 бита данной программе поддерживать не обязательно (это сейчас только микро-контроллеры всякие).

но как-то неаккуратненько.

[identity profile] dil.livejournal.com 2010-08-02 09:14 pm (UTC)(link)
не совсем. конкретно тот файл /hdd/epg.dat действительно пишется и читается на одной машине, но точно такой же формат используется для импорта EPG из внешних источников, а там он может генерироваться на машине с другой архитектурой, другим размером int'а и другим порядком байт.
ext_659502: (Default)

[identity profile] some41.livejournal.com 2010-08-02 09:17 pm (UTC)(link)
ну тогда ой

[identity profile] sem-lj.livejournal.com 2010-08-10 10:19 am (UTC)(link)
А это вообще переносимо? Разве можно надеяться, что все компиляторы расположат sid, onid и tsid в соседних ячейках памяти и именно в этом порядке?

[identity profile] dil.livejournal.com 2010-08-10 10:32 am (UTC)(link)
порядок внутри структуры - да, иначе бы на си вообще невозможно было писать переносимые программы. вот насчет выравнивания у меня есть сомнения.

[identity profile] sem-lj.livejournal.com 2010-08-10 11:36 am (UTC)(link)
Со структурой все ясно - int, как я себе представляю, будут выравнены всегда. Не ясно с &sid.