crypt of decay - Post a comment [entries|archive|friends|userinfo]
ketmar

[ userinfo | ljr userinfo ]
[ archive | journal archive ]

прелести сишечки Jun. 13th, 2018|11:19 am

ketmar
хотите простую задачку? сконвертировать 2-complement big-endian 32-bit integer в little-endian 32 integer на сишечке. машина у нас тоже little-endian.

реально, подумайте. вам только кажется что это просто. потому что правильно это делается исключительно вот так:
int32_t getBEInt (const void *ptr) {
  const uint8_t *b = (const uint8_t *)ptr;
  int32_t res = b[3]|(b[2]<<8)|(b[1]<<16)|((b[0]&0x7f)<<24);
  if (b[0] >= 0x80) {
    res ^= 0x7fffffff;
    res = -res;
    --res;
  }
  return res;
}

да-да, весь ваш чудесный код, который вы для этого используете — НЕВАЛИДНЫЙ. в нём UB. пытаетесь вдвинуть что-то в знаковый бит? UB! пытаетесь кастануть uint в int? UB для чисел вне диапазона int!

скажите спасибо дегенератам из комитета по стандартизации, которые не в курсе, что подавляющее большинство техники на планете использует для знаковой целочисленой арифметики — 2-complement. у нас же сишечка, «мощный язык для системного программирования» — поэтому представление целых со знаком там не определено для отрицательных значений. «на усмотрение разработчика компилятора», ага.

соответственно, вдвигать что-либо в знаковый бит — UB. конвертировать беззнаковое в знаковое — только [0..INT_MAX], иначе — UB.

а дегенеративные авторы дегенеративных компиляторов делают оптимизаторы для сферического кода в говне, в котором НИКОГДА НЕ ВСТРЕЧАЕТСЯ UB. внимательно это прочитайте. несколько раз. это значит, например, что для случая `uint32_t v = int32_t_variable;` компилятор вправе сказать VRP, что у `v` НИКОГДА не будет установлен старший бит. а при обратном — что int32_t никогда не будет отрицательным. и повыкидывать к ебеням все проверки на это, которые вы напишете за таким кодом.

думаете, вас это не касается? а вот хуй! gcc, например, очень даже умеет в такие «оптимизации». поэтому забейте себе во все проекты как минимум: «-fno-strict-overflow -fwrapv». конкретно эту ситуацию оно разминирует. да, я в курсе, что «-fno-strict-overflow» не нужно при «-fwrapv», но оно разминирует ещё и некоторые другие случаи (для арифметики указателей).


p.s.: тут всё ещё есть один UB, но нахуй. кто заметит (один уже заметил) — тот молодец.
Link Read Comments

Reply:
From:
(will be screened)
Identity URL: 
имя пользователя:    
Вы должны предварительно войти в LiveJournal.com
 
E-mail для ответов: 
Вы сможете оставлять комментарии, даже если не введете e-mail.
Но вы не сможете получать уведомления об ответах на ваши комментарии!
Внимание: на указанный адрес будет выслано подтверждение.
Username:
Password:
Subject:
No HTML allowed in subject
Message: