Это объявление компилируется без предупреждений в g ++ -pedantic -Wall (версия 4.6.3):
std::size_t foo = -42;
Менее заметным обманом является объявление функции с аргументом size_t и вызов ее с отрицательным значением. Может ли такая функция защитить от непреднамеренного отрицательного аргумента (который выглядит как множество квинтиллионов, подчиняющихся §4.7 / 2)?
Неполные ответы:
Простое изменение size_t на (подписанное) long отбрасывает семантику и другие преимущества size_t.
Изменение его на ssize_t — это просто POSIX, а не Standard.
Изменение его на ptrdiff_t является хрупким и иногда ломается.
Тестирование на огромные значения (набор старших битов и т. Д.) Является произвольным.
Проблема с выдачей предупреждения для этого состоит в том, что это не неопределенное поведение в соответствии со стандартом. Если вы преобразуете значение со знаком в тип без знака того же размера, вы можете позже преобразовать его обратно в значение со знаком и получить исходное значение на любом совместимом со стандартами компиляторе.
Кроме того, использование отрицательных значений, преобразованных в size_t, является довольно распространенной практикой для различных состояний ошибки — многие системные вызовы возвращают неподписанное (size_t
или же off_t
) значение для успеха или -1 (преобразуется в без знака) для ошибки. Поэтому добавление такого предупреждения в компилятор вызовет ложные предупреждения для большого количества существующего кода. POSIX пытается кодифицировать это с ssize_t
, но это прерывает вызовы, которые могут быть успешными с возвращаемым значением, превышающим максимальное значение со знаком для ssize_t
,
Следующий отрывок из частной библиотеки.
#include <limits.h>
#if __STDC__ == 1 && __STDC_VERSION__ >= 199901L || \
defined __GNUC__ || defined _MSC_VER
/* Has long long. */
#ifdef __GNUC__
#define CORE_1ULL __extension__ 1ULL
#else
#define CORE_1ULL 1ULL
#endif
#define CORE_IS_POS(x) ((x) && ((x) & CORE_1ULL << (sizeof (x)*CHAR_BIT - 1)) == 0)
#define CORE_IS_NEG(x) (((x) & CORE_1ULL << (sizeof (x)*CHAR_BIT - 1)) != 0)
#else
#define CORE_IS_POS(x) ((x) && ((x) & 1UL << (sizeof (x)*CHAR_BIT - 1)) == 0)
#define CORE_IS_NEG(x) (((x) & 1UL << (sizeof (x)*CHAR_BIT - 1)) != 0)
#endif
#define CORE_IS_ZPOS(x) (!(x) || CORE_IS_POS(x))
#define CORE_IS_ZNEG(x) (!(x) || CORE_IS_NEG(x))
Это должно работать со всеми неподписанными типами.