LINUX.ORG.RU

char это и не signed и не unsigned а непонятно что

 


3

6
> cat main.cpp
#include <type_traits>

int main() {
        static_assert((::std::is_same<char, signed char>::value) == true);
        static_assert((::std::is_same<char, unsigned char>::value) == true);

        return 0;
}

> g++ -Wall -Wextra main.cpp
main.cpp: In function 'int main()':
main.cpp:4:2: error: static assertion failed
  static_assert((::std::is_same<char, signed char>::value) == true);
  ^~~~~~~~~~~~~
main.cpp:5:2: error: static assertion failed
  static_assert((::std::is_same<char, unsigned char>::value) == true);
  ^~~~~~~~~~~~~
★★★★

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

Злые языки говорят, что некоторые обломились при переходе на 64-бита

Для этого нужно встретить реальный вектор длиннее 31/32 бит. Таких мест действительно немного.

ПыСы. Знаете как выглядит самый быстрый цикл по вектору на любой платформе из тех с которыми ваш покорный сталкивался до сих пор?

for (int i = 0, n = v.size(); i < n; ++i) {
   ...
}

Справедливо вне зависимости от того что происходит в теле цикла. Не благодарите.

ПыПыСы. Всякие там SIMD и prefetch мы в этом контексте не рассматриваем.

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

Как бы я до сего момента наивно конвертировал указатели в size_t и никто мне против не говорил. Но тут недавно мне компилятор для stm8 дал по рукам и я решил разобраться.

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

Для этого нужно встретить реальный вектор длиннее 31/32 бит. Таких мест действительно немного.

Но вот кому-то не повезло именно после перехода на 64 бита, т.к. появилась возможность создавать массивы больше 2GiB длиной.

for (int i = 0, n = v.size(); i < n; ++i)

Вроде бы нормальные компиляторы должны выдавать предупреждения на усечение unsigned (int/long) до int-а.

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

Вроде бы нормальные компиляторы должны выдавать предупреждения на усечение unsigned (int/long) до int-а.

В тех немногочисленных местах (подчёркиваю - немногочисленных) где переполнение таки возможно int меняется на size_t, и вуаля (с небольшой потерей на 64 битах).

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

Вот как определить, какая размерность должна быть у str_value когда у нас int плавает туда-сюда, а мы не хотим тратить стек под лишнее?

А что бы было, если бы инт не плавал? Значит существует ситуация, когда в int_value пихают больше положенного (раз допускается выход за проектные пределы при росте int’a) -> переполнение и мусорное значение как итог. Аналог сделать несложно:

char str_value[10];
my_int_to_str(int_value % 1e5, str_value);

Но тут вопрос - а что лучше, мусорное значение с туманной перспективой отлова, или простое обнаружение санитайзером в этой «ловушке»? Т.е. в коде уже есть проблема и она живёт задолго до my_int_to_str().

Мелочи это всё. Меня вот куда больше интересует - почему в std крестов всунули специализации локалонезависмых codecvt фасетов для utf конверсий, но нет специализации для конвертаций между utf-16<->utf-32, очень странно, видимо предлагают делать цепочку из костылей: utf-16->utf-8->utf-32. Почему-то прокси кодировкой является utf-8, я бы понял если бы в этой роли выступал utf-32.

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

А что бы было, если бы инт не плавал?

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

Чтобы пример был более реальным: представьте, что нам нужно сгенерировать строковый индентификатор на базе нескольких целочисленных значений (который затем будет использоваться в качестве имени файла/каталога, в качестве ключа в БД, в качестве параметра в URL и т.д.). И нам нужно уместиться в какой-то фиксированный размер (что особенно актуально для БД).

int32 в hex-е всегда будет 8 символов. Сколько будет int, если мы не ограничиваемся только случаями платформ на которых int всегда 32 бита? А хз.

Значит существует ситуация, когда в int_value пихают больше положенного (раз допускается выход за проектные пределы при росте int’a)

Не понял откуда вы это взяли.

my_int_to_str(int_value % 1e5, str_value);

В чем смысл этого примера не понял.

Во-первых, у вас тут double будет вместо int-а, и компилятор должен ударить по рукам.

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

Меня вот куда больше интересует - почему в std крестов всунули специализации локалонезависмых codecvt фасетов для utf конверсий

Простите, совсем не моя тема, я здесь вообще не копенгаген, а осло.

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

Сколько будет int, если мы не ограничиваемся только случаями платформ на которых int всегда 32 бита? А хз.

sizeof(int) * CHAR_BIT / 4 няп

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

sizeof(int) * CHAR_BIT / 4

Типа того.

По хорошему так и нужно делать. К сожалению, я сам далеко не всегда вспоминаю про существование CHAR_BIT :(

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

Почему-то прокси кодировкой является utf-8

Потому что БАЗА

я бы понял если бы в этой роли выступал utf-32

🤦‍♂️

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

У меня - есть. И у миллиона остальных «лемингов» - тоже.

Это неправда. Любой программист, даже изучающий, знает о пределе разрядности.

Нет. Просто int - это native register size

Глупость.

На x86_64 int 32битный.

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

Ты сам это выдумал, зачем тебе знать точную разрядность в счетчике цикла, например?

Вот именно поэтому. Твои слова как раз демонстрируют.

Есть такое понятие, идеоматичный код. Для C идеоматичный цикл, когда не нужно что-то особое, это цикл по инту. Тебе привели пример с вектором, но это уже уровень выше, кто-то извне дал тебе вектор на обработку. Я предлагаю самый простой код, цикл до тысячи, и внутри умножение счётчика на 40, без явного приведения к 32 битам. Если бы джун написал такой код, ты бы на ревью докопался до «инт гарантирует только 16 бит»?

Ну а если бы пропустил, то всё, сам понимаешь, в твоём проекте код, который неявно зависит от 32битных интов. И это произошло бы только потому, что полвека назад люди заигрались в абстрактное «целое».

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

Писать то надо чётко int_fastN_t где просить столько бит сколько нужно. А не надеяться на то что int хватит. Давно не использую int в коде. Только fast для работы и, с недавнего времени, least для хранения вместо фиксированных типов. Причём всё это typedef где то наверху чтобы коде использовать LogIndex_Store и LogIndex_Fast

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

в твоём проекте код, который неявно зависит от 32битных интов

можно static_assert добавить, тогда при смене платформы код не соберётся и компилятор подскажет что на этой платформе не выполняется.

Я так делал для long, что он 32 битный(на Windows это так) и чтобы тесты не прошли если вдруг когда-то кто-то захочет перенести это на Linux.

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

Глупость. На x86_64 int 32битный.

Внезапно: на x86_64 32 битные операции быстрее чем 64 битные, некоторые - в разы. Я уверен вы много статей на эту тему найдёте погуглив.

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

Внезапно: уже нет. Умножение что 32битное, что 64битное. Деление да, но тут такой момент: idiv 8bit быстрее 16 бит, 16 быстрее 32, 32 быстрее 64. Так что если бы латентность деления была аргументом, пришлось бы int 8битным делать.

В общем попал ты пальцем в небо.

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

В общем попал ты пальцем в небо.

Удачи в ваших изысканиях.

ПыСы. Ситуация заметно разнится между Intel и AMD. Одна из причин почему мы AMD потестировали, и выкинули на помойку.

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

Ситуация заметно разнится между Intel и AMD. Одна из причин почему мы AMD потестировали, и выкинули на помойку.

В данном случае ни в чем не разнится. И те и другие складывают, вычитают и умножают 64битные целые с той же скоростью что и 32битные, а целочисленное деление делают микрокодом и латентность операции варьируется, в пределах в нескольких десятков тактов, и верхний предел зависит от ширины операндов, меньше всего у 8битных.

Но и бог с ними, с x86. Я вот что нашел: https://en.m.wikipedia.org/wiki/64-bit_computing#64-bit_data_models

ILP64 (т.е. когда int long и pointer все 64битные) и SILP64 не используются практически нигде. Вне зависимости от железа. В основном LP64. Майкрософт стоит особняком, в их компиляторе даже long остался 32 бита. И на x86_64, и на i64

Так что нет, размер инта сейчас никак не связан с размером регистра или скоростью выполнения 64битных операций

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

И те и другие складывают, вычитают и умножают 64битные целые

Выше - правда.

с той же скоростью что и 32битные

Выше - наглая ложь. То что AMD имеет тенденцию заставлять «платить» там где можно сэкономить - это их проблемы.

и верхний предел зависит от ширины операндов, меньше всего у 8битных.

Господи. Молодой человек - слюной не захлебнитесь.

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

Поменьше фанбойства. У всех актуальных латентность и темп запуска 64 бит и 32 совпадает. Да, у Интел это случилось на 10 лет раньше, с core i*, видимо это ты и запомнил

Господи. Молодой человек - слюной не захлебнитесь.

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

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

Это правда что на Win long это 32 бита, а unsigned long - 64?

Сам-то как думаешь? Нет, конечно. Видимо кто-то неправильно понял java, которая 32битные беззнаковые предлагает обрабатывать через знаковый long.

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

Спасибки! Я тоже «поморгал» когда услышал, но решил - «ну наверное» …

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

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

Вы знаете - а я должен вам сказать «большое спасибо». Вы таки заставили меня «расчехлиться» и замерить пару вещей на «боевом железе». Результаты, мягко говоря, совсем не то что я ожидал увидеть. И таки да - нынче походу indexes 32 vs 64 бит роли не играют, по крайней мере на том что под рукой (Gold 6242R) - идут «ноздря в ноздрю» что называется. Есть еще несколько эффектов которые я пока обьяснить не могу, будем разбираться.

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

Эммм.. Я же с самого начала говорил, что 32-битному сумматору в целом всё равно, какие данные в него загнаны, 32-битные или 16-битные. По умолчанию я считал, что это верно и для 64-битного сумматора и не только сумматора, если не доказано обратное.

А «не всё равно» становится, когда мы начинаем считать arithmetic throughput. Да, я по-прежнему считаю, что грузить 8-битные данные в 64-битные сумматоры можно, но это неэффективно. Сам я так стараюсь не делать и другим на советую. Хрюндель этот аргумент кстати понял (слава богам), но продолжил кидаться какашками, потому что ему эти соображения не кажутся существенными.

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

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

32-битные или 16-битные.

Емнип: 8/16 битный load не занулял старшие разряды, ножки именно оттуда растут. При переходе 32 -> 64 учли ошибки былых поколений.

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

идут «ноздря в ноздрю»

Справедливости ради: «десктопный» i7 ведёт себя совсем по другому. И ещё почему-то неожиданно вылезает разница signed vs unsigned, не в пользу signed. Вот этого я пока объяснить не могу (ожидал наоборот, если честно). На asm буду смотреть чуть позже, но однозначно буду.

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

И ещё почему-то неожиданно вылезает разница signed vs unsigned, не в пользу signed. Вот этого я пока объяснить не могу

Арифметика над signed - UB в общем случае, а над unsigned - нет 🙂

Какие там приседания делает компилятор вокруг этого факта, я гадать не берусь, подожду Ваших выводов

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

Арифметика над signed - UB в общем случае, а над unsigned - нет

Именно. Я бы ожидал больший простор для оптимизаций в signed. А оно эвона как…

bugfixer ★★★★★
()

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

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