LINUX.ORG.RU

Есть ли какие-то зависимости от архитектур в результате приведения большего типа к меньшему?

 


1

2

Вот пример

unsigned i = string::npos;
assert(numeric_limits<unsigned>::max() == i)

На всех ли архитектурах (x86, arm, mips, прочие архитектуры с прямым и обратным порядком байт) справедливо i == numeric_limits<unsigned>::max() ?


Есть, но крайне сложно оказаться в такой ситуации, это или прыжки между 16/32/64 битными архитектурами, где совместимость ложится на плечи компилятора, где он чтото заворачивает хардварно, а чтото софтварно или же abi, где нагородили кучу стандартов, где не всё раскладывается по регистрам - вот тут оч хорошо расписаны разные случаи

sparks ★★★★
()

Вот ты пришёл сюда и об этом спросил, значит ты понимаешь что делаешь потенциально небезопасную и непереносимую херню. Так а почему бы тебе её просто не делать?

anonymous
()

На всех ли архитектурах…

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

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

А если теперь сделать c++, то как раз-таки возникнет переполнение. Поэтому вычисления вблизи границы допустимых значений типа должны выполняться с проверками на переполнение. И да, char можно без потерь привести к int, но не наоборот. Хотя, это может быть машинозависимо.

yars068 ★★★★★
()
Последнее исправление: yars068 (всего исправлений: 2)

Нет, не на всех.

Где-то int может оказаться больше чем size_t и тогда (size_t)-1 будет меньше чем максимум unsigned int-а.

Существуют ли такие архитектуры в реальности - не знаю, но это нигде не запрещено.

signed int-ы, про которые зафлудили всю тему, тут разумеется ни при чём.

firkax ★★★★★
()

В теории (судя по цппреференс), должна быть какая-то зависимость от one’s complement vs two’s complement, если в конверсии участвуют отрицательные числа. Например:

     If the destination type is unsigned, the resulting value is the smallest unsigned value equal to the source value modulo 2n
    where n is the number of bits used to represent the destination type. 

        That is, depending on whether the destination type is wider or narrower, signed integers are sign-extended[1] or truncated and unsigned integers are zero-extended or truncated respectively. 

Тут же сноска

This only applies if the arithmetic is two's complement which is only required for the exact-width integer types. Note, however, that at the moment all platforms with a C++ compiler use two's complement arithmetic.

В общем что-то может где-то быть, но это какая-то пипец маргинальщина, под которую даже компилятора нет

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

Вот и я сейчас склоняюсь что не будет никакого UB.

Вот например пусть есть тип T1 он 1 байт, и тип T2 он пусть два байта

и так:

T2 = [0xFF][0xFF]

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

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

UB нет, но проблема может быть - я выше ещё ответил.

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

Отбросится всегда старшая часть, такова спецификация Си, от железа это не зависит.

Всегда так: (unsigned int8)0x1234 == 0x34

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

$firkax поясни за диз. Вопрос с отрицательными числами сильно интереснее изначального (ответ на который очевиден), получается, что, типичный код:

int main() {
    unsigned long long ul = -1;
    assert(ul + 1 == 0);
}

не является переносимым. Что в общем-то логично для разного представления отрицательных чисел. Но компилятор могу там вставлять необходимые прибавки при конверсии. К счастью one’s complement вряд ли кто-то в глаза видел

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

Этот код переносимый. -1, скастованное в любой unsigned, приводится к максимальному значению того unsigned-а. Сначала signe -1 приводится к нужной разрябности (очевидно, это можно сделать без проблем т.к. -1 представимо в любом signed типе), а затем конвертируется в unsigned по правилам unsigned. Внутреннее представление чисел тут значения не имеет. Для современных процов описанные правила нативные, для других - будет получаться какой-то сложный код чтоб эмулировать то же самое.

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

Я не сам придумал, а посмотрел здесь, пункт Integral conversions.

а затем конвертируется в unsigned по правилам unsigned. Внутреннее представление чисел тут значения не имеет

Получается, что имеет, там черным по белому написано. Наверное, из-за неактуальности one’s complement просто никто не заморачивался. А зачем, если нет ни одного компилятора, умеющего генерить код под такое железо

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

Я не знаю, что означает эта сноска, смотри пункт выше (он без сносок)

If the destination type is unsigned, the resulting value is the smallest unsigned value equal to the source value modulo 2^n
where n is the number of bits used to represent the destination type. 

тут по-моему всё однозначно расписано - исходное и новое числа должны быть равны по модулю 2^n.

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

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

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

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

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

Следи за словами, я тебя и проклясть могу. Ты, похоже, даже не очень понял суть своего любимого 1 пункта, там говорится, что беззнаковый приёмник равен остатку от деления 2^n. Понятно, что это касается случаев, когда источник больше приёмника. Сюда никак не могут входить случаи, когда источник меньше и надо делать sign-extension. Подпункт со сноской как раз конкретизирует это и объясняет что приосходит когди источник меньше и больше приёмника.

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

Понятно, что это касается случаев, когда источник больше приёмника.

Вот же ты упёртый. Нет там никаких оговорок! Это относится ко всем случаям. И не «остатку от деления», а «наименьшему представимому числу, равному по модулю».

надо делать sign-extension

sign-extension - это технические подробности того, как будет достигаться описанное в первом абзаце, вот видимо они и зависят от представления. А само правило указано в первом абзаце и оно не меняется.

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

modulo 2^n это не операция, а условие к уравнению.

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

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

О боги, да ты просто токсичный кусок говна, который даже дискуссию не может вести конструктивно. Прощай

PS: firkax - это не ник, а быстро прогрессирующее заболевание нервной системы, проявляющееся расстройством интеллекта

anonymous
()
29 декабря 2024 г.
Ответ на: комментарий от rupert

не тот же, что unsigned

это где такая гарантия?

Поэтому unsigned i = string::npos должо быть UB

не должно быть.

Но unsigned i = -1 определено

это оно определено для size_t — а эта константа неизвестно заранее как превратится в unsigned — с трункацией или без такового. Это уже имплементейшн дефайнед какие размеры данных типов на конкретной архитектуре.

safocl ★★
()