В C99 есть некоторые (необязательные) типы, такие как int8_t
, int16_t
и им подобные, которые гарантированно имеют точно заданную ширину и не содержат битов заполнения, а также представляют числа в дополнении до двух (7.18.1.1). В 6.2.6.2 переполнение целого числа со знаком упоминается как сноски 44) и 45), а именно то, что оно может привести к перехвату значений в битах заполнения.
Поскольку intN_t
не имеет битов заполнения, и они гарантированно являются дополнением до двух, означает ли это, что их переполнение не приводит к неопределенному поведению? Каков будет результат, например. переполненное умножение? Что насчет дополнения? Уменьшается ли результат по модулю 2^N
, как для беззнаковых типов?
uintN_t
переполнение не (обычно) четко определено. ИintN_t
, иuintN_t
по-прежнему подлежат целочисленному преобразованию, и умножение двух значенийuint16_t
в системах, гдеuint16_t
преобразуется вint
, может привести к результату, который не может быть представлен вint
. - person   schedule 14.06.2015int8_t
,int16_t
, не являются полностью необязательными в C99: эти типы являются необязательными. Однако, если реализация предоставляет целочисленные типы шириной 8, 16, 32 или 64 бита, без битов заполнения и (для типов со знаком) с представлением в дополнительном коде до двух, она должна определить соответствующие имена typedef. §7.20.1.1 3 - person chux - Reinstate Monica   schedule 14.06.2015int
, компилятор должен либо генерировать код, который будет вести себя так, как если бы оператор принудил свои операнды к этому типу и выполнил операцию, используя этот тип, или иначе определить__STDC_NON_MODULAR_UNSIGNED_SHORT
. Обратите внимание, что почти все компиляторы, выпущенные до 2010 года (и многие выпущенные позже), уже соответствуют этому правилу, и большинство из них можно заставить соответствовать... - person supercat   schedule 16.06.2015(unsigned short) ((unsigned short) 65535 * (unsigned short) 65535)
, - это случай, когда текущие часто используемые реализации не соответствуют предложенному вами правилу, по крайней мере, в некоторых из их соответствующих режимов, и из-за этого макрос функции не был бы очень полезен. Кроме того, я думаю, что макрос функции должен быть наоборот: если макрос не определен, вы не знаете, потому ли это, что он поддерживает операции, или потому, что он придерживается более старого стандарта. Сделать это__STDC_MODULAR_UNSIGNED_SHORT
: если это определено, вы знаете, что это сработает. - person   schedule 16.06.2015#if (__STDC_MODULAR_UNSIGNED_SHORT>0)
#error ...
к коду, который в настоящее время используется с устаревшим компилятором, где неподписанные шорты всегда работали должным образом, не повлияет на его поведение в этом компиляторе, но гарантирует, что если он будет перемещен в более новый компилятор, он либо будет работать, как ожидалось, либо выйдет из строя. компиляция. Только компиляторы, которые достаточно новы, чтобы проявить творческий подход, но недостаточно новы, чтобы об этом сказать, могут создавать проблемы. - person supercat   schedule 16.06.2015x*=x;
безусловно безопасен, и программист, который готов принять неопределенное поведение, когдаx
выходит за пределы, может написатьx=(int)(x*x)
, чем тот, где программисты, желающие нормального поведения, должны писатьx*=1u*x;
, и где неспособность написать это приведет к тому, что программа будет часто работать в любом случае (даже с запредельными значениями x), но может в какой-то более поздний момент перестать подчиняться законам времени и причинно-следственной связи. - person supercat   schedule 16.06.2015typedef struct { int32_t left, top, bottom, right; } RECT; int32_t bb_right(RECT *rects, int32_t count) { int32_t max_x = INT_MIN; for (int32_t i=0; i<count; i++) { int32_t r=rects[i].left + rects[i].width; if (r > max_x) max_x = r; } return max_x;}
. Функция должна возвращать крайнюю правую координату заданных прямоугольников, если ширина каждого прямоугольника неотрицательна и не превышает INT32_MAX-left. Если функции разрешено возвращать любое произвольное значение, но нет других побочных эффектов, при указании указателя на доступный массив, содержащий недопустимые прямоугольники... - person supercat   schedule 17.06.2015uint32_t r = 0x80000000u+rects[i].left+rects[i].width;
и определение вычисленного таким образом максимальногоr
будет работать, но я не думаю, что программист имеет право ожидать, что это будет так же быстро, как оригинал (возможно, некоторые оптимизаторы могли бы понять, что они могут избежать дополнительного добавления 0x80000000, если они использовать операцию сравнения со знаком, но это кажется чрезмерно оптимистичным). - person supercat   schedule 17.06.2015int32_t sum(int32_t *dat, int32_t count);
. Возвращает итог, если промежуточное значение не переполняется. ВозвратитеINT32_MIN
, если результат не может быть представлен вint32_t
. Произвольно вернуть либо правильную сумму, либоINT32_MIN
, если промежуточные значения не помещаются вint32_t
, но сумма может. Есть ли какой-либо способ написать код C, который дал бы что-то близкое к оптимальному коду, отвечающему этим требованиям как на 32-битных, так и на 64-битных платформах, имея в виду, что... - person supercat   schedule 17.06.2015int32_t
, но, например, ARM7-TDMI цикл может быть развернут для использования инструкции загрузки-множества, последовательности инструкций сложения, если не переполнения, инструкции вычитания 1, если не переполнения на счетчике (предварительно инициализированного, поэтому последний цикл перенесет его от 0x80000000 до 0x7FFFFFFFF) и ветвь, если не переполнение. Гораздо быстрее, чем оптимальный код для вычисления 64-битного итога. - person supercat   schedule 17.06.2015uintN_t
. Мои комментарии были ответом на это предложение. Если ваш конкретный пример того, почему этот макрос функции хорош, работает только дляintN_t
, тогда может сработать другое предложение, но не то, которое вы на самом деле сделали. - person   schedule 17.06.2015int
правильно работает со всеми размерамиint
. Сказать, чтоfoo *= foo;
будет иметь тот же эффект, что иfoo *= 1u*foo;
во всех случаях, где оно определено, но может свести на нет законы времени и... - person supercat   schedule 18.06.2015int
; моя предпочтительная нормативная семантика неявно заставляла бы работать модульную арифметику с короткими беззнаковыми значениями, даже если компиляторы не имели для этого специальной обработки (и были бы полезны в других местах), но на самом деле ничего не получается, взламывая существующий код. - person supercat   schedule 18.06.2015