LINUX.ORG.RU

Объясните сишную магию

 ,


11

14

Пытался понять как реализовать SVG фильтр feComposite, ибо SVG дока унылая, поэтому залез в сорцы вебкита. Там тоже документации ноль, ещё и код очень странный.

Вот что это за ужас (src):

static unsigned char clampByte(int c)
{
    unsigned char buff[] = { static_cast<unsigned char>(c), 255, 0 };
    unsigned uc = static_cast<unsigned>(c);
    return buff[!!(uc & ~0xff) + !!(uc & ~(~0u >> 1))];
}

Я так понимаю, они проверяют что int в 0..255 диапазоне, но уж слишком странным образом.

UPD: коммит, который добавил этот код.

★★★★★

Последнее исправление: RazrFalcon (всего исправлений: 1)

Ответ на: комментарий от Harald

И что изменится, если я больше массив обработаю?

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>

#define NUMB 10
#define ARRAY_SIZE 64*1024*1024

uint64_t rdtsc( void ) {
   union sc {
      struct { uint32_t lo, hi; } r;
      uint64_t f;
   } sc;
   __asm__ __volatile__ ( "rdtsc" : "=a"( sc.r.lo ), "=d"( sc.r.hi ) );
   return sc.f;
}

unsigned calibr( int rep ) {
   uint64_t n, m, sum = 0;
   n = m = ( rep >= 0 ? NUMB : rep );
   while( n-- ) {
      uint64_t cf, cs;
      cf = rdtsc();
      cs = rdtsc();
      sum += cs - cf;
   }
   return (uint32_t)( sum / m );
}

unsigned char clampByteSimple(int c)
{
    if(c < 0) return 0;
    else if(c > 255) return 255;
    else return (unsigned char)c;
}

static unsigned char clampByte(int c)
{
    unsigned char buff[] = { static_cast<unsigned char>(c), 255, 0 };
    unsigned uc = static_cast<unsigned>(c);
    return buff[!!(uc & ~0xff) + !!(uc & ~(~0u >> 1))];
}

int main()
{
    std::vector<int> array(ARRAY_SIZE);
    
    srand(time(NULL));
    for(int i = 0; i < ARRAY_SIZE; i++) 
        array.push_back(-1000+ rand() % 1000);
    
    long cali = calibr(1000);
    
    unsigned long long t2 = rdtsc();
    for (auto i = array.begin(); i != array.end(); i++)
        clampByteSimple(*i);
    t2 = rdtsc() - t2 - cali;
    
    unsigned long long t1 = rdtsc();
    for (auto i = array.begin(); i != array.end(); i++)
        clampByte(*i);
    t1 = rdtsc() - t1 - cali;
    
    std::cout << "clampByte: " << t1 << std::endl;
    std::cout << "clampByteSimple: " << t2 << std::endl;
}
clampByte: 9250192627
clampByteSimple: 8198114399

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

Результат каста определён таким образом, что в two’s complement достаточно просто биты ...
...

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

На конкретный вопрос:

Twos-complement стандартизован?

Нет.

Зачем строишь предположения про дополнительный код, если допролнительного кода нет?
А то, что в стандарте описаны свойства, похожие на свойства дополнительно кода - это просто совпадение, а не причино-следственная связь.

anonymous
()
Ответ на: комментарий от anonymous
  • Конвертируешь один раз входные данные под формат локальной машины(в нашем случае no-op)
  • Профит
anonymous
()
Ответ на: комментарий от anonymous

Ты сразу предполагаешь

Что я предполагаю?

Зачем строишь предположения про дополнительный код, если допролнительного кода нет?

Что?

А то, что в стандарте описаны свойства, похожие на свойства дополнительно кода - это просто совпадение, а не причино-следственная связь.

Что?

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

анонимус, назови с ходу живые машины, применяемые в суровом продакшене в 2019 году, у которых не two’s complement

Harald ★★★★★
()
Ответ на: комментарий от Harald
$ lscpu
Architecture:        aarch64
Byte Order:          Little Endian
CPU(s):              8
On-line CPU(s) list: 0-7
Thread(s) per core:  1
Core(s) per socket:  4
Socket(s):           2
Vendor ID:           Qualcomm
Model:               4
Model name:          Kryo V2
Stepping:            0xa
CPU max MHz:         2208.0000
CPU min MHz:         633.6000
BogoMIPS:            38.40
L1d cache:           32K
L1i cache:           32K
L2 cache:            1024K
Flags:               fp asimd evtstrm aes pmull sha1 sha2 crc32
$ clang --version
clang version 7.0.0 (tags/RELEASE_700/final)
Target: aarch64--linux-android
Thread model: posix                                     InstalledDir: /data/data/com.termux/files/usr/bin
$ clang -O3 n.cpp
$ ./a.out
initialized source buffer
Test #1, random data:
clampByte(): 183914 clocks clampsum 8558541649
clampByteSimple(): 39857 clocks clampsum 8558541649
clampByte_tsar(): 125654 clocks clampsum 8558541649
orig vs simple: 0.216715x, tsar vs simple: 0.317196x
Test #2, -1,127,257,0:
clampByte(): 167556 clocks clampsum 9622049179
clampByteSimple(): 39852 clocks clampsum 9622049179
clampByte_tsar(): 125664 clocks clampsum 9622049179
orig vs simple: 0.237843x, tsar vs simple: 0.317131x
Test #3, preclamped data:
clampByte(): 168710 clocks clampsum 17112727680
clampByteSimple(): 39799 clocks clampsum 17112727680
clampByte_tsar(): 125829 clocks clampsum 17112727680
orig vs simple: 0.235902x, tsar vs simple: 0.316294x
Test #4, 257:
clampByte(): 181852 clocks clampsum 17112760320
clampByteSimple(): 39869 clocks clampsum 17112760320
clampByte_tsar(): 125715 clocks clampsum 17112760320
orig vs simple: 0.219239x, tsar vs simple: 0.317138x
Test #4, -1:
clampByte(): 180140 clocks clampsum 0
clampByteSimple(): 39825 clocks clampsum 0
clampByte_tsar(): 127621 clocks clampsum 0
orig vs simple: 0.221078x, tsar vs simple: 0.312057x
WitcherGeralt ★★
()
Ответ на: комментарий от anonymous

ты тот самый 5-звездочник

Э-э-э! Вообще-то, у меня больше. Просто не все влезают.

Игнор.

Ой.

Почему меня всё время упорят игнорутые игнорят упоротые?

i-rinat ★★★★★
()
Ответ на: комментарий от Harald

Я не эксперт. Вроде, армы есть такие.
Я просто знаю, что можно реализовать разное предстваление чисел. Например, возможны хитрые endian, когда «правые» биты - не «младшие» биты, и поиск по маске (& 0x0...0FF) и сдвиги ничего хорошего не дадут.

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

анонимус, назови с ходу живые машины, применяемые в суровом продакшене в 2019 году, у которых не two’s complement

Ты хотел написать «у которых не дополнительный код»?

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

Вставляй хотя бы табуляцию, а то непонятно при таких длинах чисел.

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

Например, возможны хитрые endian, когда «правые» биты

Оконечность имеет значение, когда в память пишешь словами, а читаешь байтами. В том случае, если в функцию приходит int, ты никак не сможешь понять, какой он там, little endian или big endian. Какая разница, если работаешь с числом как единым объектом?

i-rinat ★★★★★
()

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

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

Еще один 5-звездочник. Эксперт по съезжанию с темы. Я сказал:

Я не эксперт.

Зачем ты интересуешься тем, чему нельзя доверять? Если программируешь микроконтроллеры, ты думаю знаешь, что такое железо есть.

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

Так там по ссылке эта функция для ARM и не используется. Там отдельная реализация. Но я не могу найти нужный include. Его нет в дереве.

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

А ведь я искренне пытался понять что делает этот код (и понял).

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

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

Если по стандарту, этот код без привязки к конкретному железу, неизвестно что делает (может форматнуть флешкарту с биткойн-кошельками), используя паттерн магические числа.
Правильный вариант дан здесь: Объясните сишную магию (комментарий)

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

Ещё один ничего не понял.

Вынеси «названия» «схем», обсуждаемых в топике в «тему». Может меньше «мусорить» в топе будут.

Что то вроде: Для сравнения, известны схемы: simple(branch), cmp, tsar, MS, std.(в виде ссылок на комменты)

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

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

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

компилятор выкидывает то, что не влияет на конечный результат вычислений

Да, и некоторые компиляторы могут и последствия цикла просто во время компиляции посчитать. У Clang иногда так получается.

i-rinat ★★★★★
()
Ответ на: комментарий от RazrFalcon

Приходить на LOR за пониманием — очень странная затея.

quantum-troll ★★★★★
()
Ответ на: комментарий от i-rinat

До меня наконец-то дошло. Сейчас написал аналогичную упрощенную программу и увидел, что там заранее все подсчитать можно.

Deleted
()

Эти бенчеры комнатные. Я накатал вам бенчмарк нормальный:

#include <stdint.h>
#include <limits>
#include <algorithm>
#include <functional>
#include <random>
#include <chrono>


extern "C" namespace clamp {
#ifndef no_inline
#define no_inline  __attribute__((noinline))
#endif
  
  no_inline uint8_t std(int32_t c) {
    using limits = std::numeric_limits<uint8_t>;
    return std::clamp<int32_t>(c, limits::min(), limits::max());
  }
  
  no_inline uint8_t tsar(int32_t c) {
    uint32_t uc = c;
    uint32_t res = 255 * !(c < 0);
    if(uc < 255) return uc;
    return res;
  }
  
  no_inline uint8_t webkit(int32_t c) {
    uint8_t buff[] = { static_cast<uint8_t>(c), 255, 0 };
    uint32_t uc = static_cast<uint32_t>(c);
    return buff[!!(uc & ~0xff) + !!(uc & ~(~0u >> 1))];
  }
  
  no_inline uint8_t ffmpeg(int32_t c) {
    if (c&(~0xFF)) return (~c)>>31;
    return c;
  }
  
  no_inline uint8_t lamerok(int32_t c) {
    if(c < 0) return 0;
    else if(c > 255) return 255;
    else return (unsigned char)c;
  }
  
  no_inline uint8_t naive(int32_t c) {
    if(c < 0) return 0;
    if(c > 255) return 255;
    return c;
  }
  
};

struct config_t {
  struct data {
    using type = int32_t;
    static constexpr auto min = -512, max = 512;
    static constexpr auto size = 1024ul * 1000 * 100;
  };
};

template<typename config> struct generator {
  static inline auto data = ([] {
    fprintf(stderr, "%s\n", __PRETTY_FUNCTION__);
    auto gen = std::bind(std::uniform_int_distribution{config::data::min, config::data::max}, std::mt19937{});
    static std::vector<typename config::data::type> data(config::data::size);
    for(auto & x: data) x = gen();
    return data;
  })();
};

template<auto f, typename config = config_t> __attribute__((noinline)) void bench(const char * name) {
  auto data = generator<config>::data;  
  auto now = std::chrono::high_resolution_clock::now;
  size_t sum = 0;
  
  auto start = now();
  asm("//begin");
  for(auto & x: data) sum += f(x);
  asm("//end");
  auto time = std::chrono::duration<double>(now() - start).count();
  
  fprintf(stderr, "%s\t %.3fsec(%lucps), sum = %lu\n", name, time, size_t(config::data::size / time), sum); 
}
#define bench(fun) bench<fun>(#fun);


int main() {
  
  bench(clamp::std);
  bench(clamp::ffmpeg);
  bench(clamp::naive);
  bench(clamp::lamerok);
  bench(clamp::webkit);
  bench(clamp::tsar);
  
}

Собирать:

g/clang++ main.cpp -O3 -march=native -std=gnu++2a -fwhole-program//общий случай

-O3 -march=native -std=gnu++2a -fwhole-program -fno-unroll-loops//ещё более общий случай

//случай с инлайном.

-O3 -march=native -std=gnu++2a -fwhole-program -Dno_inline=inline -fno-tree-vectorize//всегда


-O3 -march=native -std=gnu++2a -fwhole-program -Dno_inline=inline -fno-tree-vectorize -fno-unroll-loops//более общий случай

По поводу всей фигни. Почему-то с моим кодом гцц обосрался. Я родил тоже, что родили в ffmpeg. Но почему-то у них он осилил вставить cmov, а у меня нет. Хотя я, вроде как, ему помогал.

std::clamp - это версия через ?:. Хотя это через ?: человек и напишет. С ифами почему-то они не могут.

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

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

NishiragiShintaro
()

Тоже самое и касается самой генерации данных. Пациенты генерируют данные на весь диапазон интов и очевидно, что значений в диапазоне 0-255 там куда меньше, чем в <0 >255.

NishiragiShintaro
()
Ответ на: комментарий от NishiragiShintaro
g++ -O3 -march=native -fwhole-program
clamp::std       0.124sec(823730511cps), sum = 9807621259
clamp::ffmpeg    0.125sec(821518964cps), sum = 9807621259
clamp::naive     0.380sec(269508330cps), sum = 9807621259
clamp::lamerok   0.380sec(269366478cps), sum = 9807621259
clamp::webkit    0.174sec(587322036cps), sum = 9807621259
clamp::webkitv2  0.184sec(555120750cps), sum = 9807621259
clamp::tsar      0.125sec(822486471cps), sum = 9807621259

clang++ -O3 -march=native -fwhole-program
clamp::std       0.148sec(691598098cps), sum = 9809494115
clamp::ffmpeg    0.128sec(803057843cps), sum = 9809494115
clamp::naive     0.373sec(274733908cps), sum = 9809494115
clamp::lamerok   0.372sec(275400520cps), sum = 9809494115
clamp::webkit    0.148sec(693875212cps), sum = 9809494115
clamp::webkitv2  0.148sec(693399792cps), sum = 9809494115
clamp::tsar      0.263sec(388688840cps), sum = 9809494115

g++ -O3 -march=native -fwhole-program -fno-tree-vectorize
clamp::std       0.148sec(694214621cps), sum = 9807621259
clamp::ffmpeg    0.148sec(692228689cps), sum = 9807621259
clamp::naive     0.387sec(264577551cps), sum = 9807621259
clamp::lamerok   0.387sec(264782446cps), sum = 9807621259
clamp::webkit    0.176sec(583240310cps), sum = 9807621259
clamp::webkitv2  0.196sec(521492033cps), sum = 9807621259
clamp::tsar      0.148sec(693613083cps), sum = 9807621259

clang++ -O3 -march=native -fwhole-program -fno-tree-vectorize
clamp::std       0.147sec(694899836cps), sum = 9809494115
clamp::ffmpeg    0.127sec(807550528cps), sum = 9809494115
clamp::naive     0.372sec(275142552cps), sum = 9809494115
clamp::lamerok   0.372sec(275638668cps), sum = 9809494115
clamp::webkit    0.147sec(694603869cps), sum = 9809494115
clamp::webkitv2  0.148sec(690370287cps), sum = 9809494115
clamp::tsar      0.264sec(387756738cps), sum = 9809494115

g++ -O3 -march=native -fwhole-program -fno-tree-vectorize -fno-unroll-loops
clamp::std       0.147sec(695143264cps), sum = 9807621259
clamp::ffmpeg    0.148sec(691922345cps), sum = 9807621259
clamp::naive     0.387sec(264307381cps), sum = 9807621259
clamp::lamerok   0.387sec(264852267cps), sum = 9807621259
clamp::webkit    0.175sec(584791040cps), sum = 9807621259
clamp::webkitv2  0.197sec(520602262cps), sum = 9807621259
clamp::tsar      0.147sec(695211819cps), sum = 9807621259

clang++ -O3 -march=native -fwhole-program -fno-tree-vectorize -fno-unroll-loops
clamp::std       0.148sec(691082480cps), sum = 9809494115
clamp::ffmpeg    0.127sec(805183310cps), sum = 9809494115
clamp::naive     0.373sec(274194381cps), sum = 9809494115
clamp::lamerok   0.372sec(274920585cps), sum = 9809494115
clamp::webkit    0.148sec(692147135cps), sum = 9809494115
clamp::webkitv2  0.148sec(692752107cps), sum = 9809494115
clamp::tsar      0.265sec(386907718cps), sum = 9809494115

g++ -O3 -march=native -fwhole-program -fno-tree-vectorize -funroll-all-loops
clamp::std       0.094sec(1094080693cps), sum = 9807621259
clamp::ffmpeg    0.094sec(1089048704cps), sum = 9807621259
clamp::naive     0.336sec(304559741cps),  sum = 9807621259
clamp::lamerok   0.336sec(304506135cps),  sum = 9807621259
clamp::webkit    0.166sec(615997558cps),  sum = 9807621259
clamp::webkitv2  0.173sec(593272775cps),  sum = 9807621259
clamp::tsar      0.094sec(1083637513cps), sum = 9807621259

clang++ -O3 -march=native -fwhole-program -fno-tree-vectorize -funroll-all-loops
clamp::std       0.148sec(693503861cps), sum = 9809494115
clamp::ffmpeg    0.127sec(807381147cps), sum = 9809494115
clamp::naive     0.373sec(274827068cps), sum = 9809494115
clamp::lamerok   0.371sec(275816868cps), sum = 9809494115
clamp::webkit    0.147sec(695117622cps), sum = 9809494115
clamp::webkitv2  0.147sec(695155034cps), sum = 9809494115
clamp::tsar      0.264sec(388245133cps), sum = 9809494115

g++ -O3 -march=native -fwhole-program -funroll-all-loops
clamp::std       0.094sec(1095141884cps), sum = 9807621259
clamp::ffmpeg    0.094sec(1086455837cps), sum = 9807621259
clamp::naive     0.336sec(305082211cps),  sum = 9807621259
clamp::lamerok   0.336sec(304893068cps),  sum = 9807621259
clamp::webkit    0.166sec(615939049cps),  sum = 9807621259
clamp::webkitv2  0.171sec(599872988cps),  sum = 9807621259
clamp::tsar      0.094sec(1090561981cps), sum = 9807621259

clang++ -O3 -march=native -fwhole-program -funroll-all-loops
clamp::std       0.147sec(694978243cps), sum = 9809494115
clamp::ffmpeg    0.127sec(807071408cps), sum = 9809494115
clamp::naive     0.372sec(275310751cps), sum = 9809494115
clamp::lamerok   0.372sec(275610766cps), sum = 9809494115
clamp::webkit    0.149sec(688440622cps), sum = 9809494115
clamp::webkitv2  0.148sec(692547781cps), sum = 9809494115
clamp::tsar      0.263sec(388982296cps), sum = 9809494115

g++ -O3 -march=native -fwhole-program -Dno_inline=inline -fno-tree-vectorize
clamp::std       0.085sec(1203095772cps), sum = 9807621259
clamp::ffmpeg    0.201sec(508234223cps),  sum = 9807621259
clamp::naive     0.323sec(317216492cps),  sum = 9807621259
clamp::lamerok   0.323sec(317264024cps),  sum = 9807621259
clamp::webkit    0.088sec(1161350640cps), sum = 9807621259
clamp::webkitv2  0.099sec(1030800635cps), sum = 9807621259
clamp::tsar      0.200sec(512697640cps),  sum = 9807621259

clang++ -O3 -march=native -fwhole-program -Dno_inline=inline -fno-tree-vectorize
clamp::std       0.063sec(1638325239cps), sum = 9809494115
clamp::ffmpeg    0.072sec(1412434249cps), sum = 9809494115
clamp::naive     0.063sec(1637988144cps), sum = 9809494115
clamp::lamerok   0.063sec(1620637527cps), sum = 9809494115
clamp::webkit    0.076sec(1341969360cps), sum = 9809494115
clamp::webkitv2  0.077sec(1332915773cps), sum = 9809494115
clamp::tsar      0.199sec(514590999cps),  sum = 9809494115

g++ -O3 -march=native -fwhole-program -Dno_inline=inline -fno-tree-vectorize fno-unroll-loops
clamp::std       0.063sec(1617866504cps), sum = 9809494115
clamp::ffmpeg    0.073sec(1407045922cps), sum = 9809494115
clamp::naive     0.063sec(1616290235cps), sum = 9809494115
clamp::lamerok   0.063sec(1634527503cps), sum = 9809494115
clamp::webkit    0.076sec(1341784514cps), sum = 9809494115
clamp::webkitv2  0.077sec(1332517114cps), sum = 9809494115
clamp::tsar      0.199sec(514415499cps),  sum = 9809494115

clang++ -O3 -march=native -fwhole-program -Dno_inline=inline -fno-tree-vectorize fno-unroll-loops
clamp::std       0.062sec(1641228453cps), sum = 9809494115
clamp::ffmpeg    0.072sec(1414943692cps), sum = 9809494115
clamp::naive     0.063sec(1631400586cps), sum = 9809494115
clamp::lamerok   0.063sec(1631484775cps), sum = 9809494115
clamp::webkit    0.077sec(1333625498cps), sum = 9809494115
clamp::webkitv2  0.076sec(1342215901cps), sum = 9809494115
clamp::tsar      0.199sec(513468761cps),  sum = 9809494115

g++ -O3 -march=native -fwhole-program -Dno_inline=inline -fno-tree-vectorize -funroll-all-loops
clamp::std       0.071sec(1434655263cps), sum = 9807621259
clamp::ffmpeg    0.208sec(492341699cps),  sum = 9807621259
clamp::naive     0.281sec(364864594cps),  sum = 9807621259
clamp::lamerok   0.281sec(363959646cps),  sum = 9807621259
clamp::webkit    0.071sec(1437228444cps), sum = 9807621259
clamp::webkitv2  0.083sec(1238082204cps), sum = 9807621259
clamp::tsar      0.197sec(520746089cps),  sum = 9807621259

clang++ -O3 -march=native -fwhole-program -Dno_inline=inline -fno-tree-vectorize -funroll-all-loops
clamp::std       0.063sec(1632801866cps), sum = 9809494115
clamp::ffmpeg    0.073sec(1400604130cps), sum = 9809494115
clamp::naive     0.063sec(1627131942cps), sum = 9809494115
clamp::lamerok   0.064sec(1611998584cps), sum = 9809494115
clamp::webkit    0.076sec(1338611873cps), sum = 9809494115
clamp::webkitv2  0.077sec(1329015452cps), sum = 9809494115
clamp::tsar      0.199sec(514416378cps),  sum = 9809494115


gcc (Gentoo 8.3.0-r1 p1.1) 8.3.0
clang version 9.0.0 + libc++

  no_inline uint8_t webkitv2(int32_t c) {
    return ((uint8_t[]){(uint8_t)c, 255, 0})[(c < 0) + ((uint32_t)c > 255)];
  }
NishiragiShintaro
()
Ответ на: комментарий от i-rinat

Меня беспокоят Deleted-ы, оригинальный ник которых я не могу восстановить :)

Harald ★★★★★
()
Ответ на: (unsigned)c > 255 от anonymous

Заодно, чтобы избавится от магического числа

c > UCHAR_MAX

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

Если по стандарту, этот код без привязки к конкретному железу, неизвестно что делает (может форматнуть флешкарту с биткойн-кошельками)

Довен, там нет UB.

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

Без массива

unsigned char clampBait(int c)
{
	return ((unsigned char)c | 0xff00u) >> ((c < 0) + (c > 255u)) * 8;
}

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

Довен, там нет UB.

Где в стандарте написано про побитовое представление типов int и unsigned int? Если не написано, то применение битовых масок для этих типов - это UB. Битовые маски можно применять только если ты сам туда записал биты и работаешь с битами.

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

приведение типа здесь лишнее

Нет, не лишнее.

Ты прав.

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

Где в стандарте написано про побитовое представление типов int и unsigned int?

[basic.types], например.

Если не написано, то применение битовых масок для этих типов - это UB. Битовые маски можно применять только если ты сам туда записал биты и работаешь с битами.

Ньюфаг узнал про UB и теперь оно ему мерещится на каждом шагу?

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

[basic.types], например.

Давай цитаты оттуда, где написано про то, какие именно битовые операции имеют смысл для таких типов?

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

А теперь дай побитовое представление числа "-1". Заметь, разрешается прямой, обратный и дополнительный код, а возможно еще какие-нибудь другие (позиционные) двоичные системы.

[ Example: This International Standard permits two's complement, ones' complement and signed magnitude representations for integral types.  — end example ]

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

Implementation-defined

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

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

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

IDB от UB отличается фундаментально.

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