Как я говорю, подписывается ли целочисленная переменная C?

Часто, OutputCaching может быть самым быстрым и эффективным, но только когда он отвечает Вашим требованиям. Никакой смысл в наличии быстро эффективного, если это неправильно! ;)

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

8
задан a3f 31 March 2015 в 02:16
поделиться

7 ответов

#define ISVARSIGNED(V)  ((V)<0 || (-V)<0 || (V-1)<0)

не меняет значение V. Третий тест обрабатывает случай, когда V == 0.

В моем компиляторе (gcc / cygwin) это работает для int и long , но не для char или short .

#define ISVARSIGNED(V) ((V)-1<0 || -(V)-1<0)

также выполняет свою работу в двух тестах.

6
ответ дан 5 December 2019 в 10:43
поделиться

Если вы используете GCC, вы можете использовать ключевое слово typeof , чтобы не перезаписывать value:

#define ISVARSIGNED(V) ({ typeof (V) _V = -1; _V < 0 ? 1 : 0 })

Это создает временную переменную _V , которая имеет тот же тип, что и V .

Что касается переносимости, я не знаю. Он будет работать на машине с двумя комплиментами (то есть со всем, на чем ваш код когда-либо будет работать, по всей вероятности), и я верю, что он также будет работать на машине комплиментов и знаков и величин. В качестве примечания: если вы используете typeof , вы можете преобразовать -1 в typeof (V) , чтобы сделать его более безопасным (т.е. с меньшей вероятностью срабатывания) предупреждения).

5
ответ дан 5 December 2019 в 10:43
поделиться
#define ISVARSIGNED(V) ((-(V) < 0) != ((V) < 0))

Без уничтожения значения переменной. Но не работает для значений 0.

А как насчет:

#define ISVARSIGNED(V) (((V)-(V)-1) < 0)
5
ответ дан 5 December 2019 в 10:43
поделиться

Отличительной особенностью математики со знаком / без знака является то, что при сдвиге вправо числа со знаком копируется самый старший бит. Когда вы сдвигаете беззнаковое число, новые биты равны 0.

#define HIGH_BIT(n) ((n) & (1 << sizeof(n) * CHAR_BITS - 1))
#define IS_SIGNED(n) (HIGH_BIT(n) ? HIGH_BIT(n >> 1) != 0 : HIGH_BIT(~n >> 1) != 0

По сути, этот макрос использует условное выражение, чтобы определить, установлен ли старший бит числа. Если это не так, макрос устанавливает его путем побитового отрицания числа. Мы не можем выполнить арифметическое отрицание, потому что -0 == 0. Затем мы сдвигаемся вправо на 1 бит и проверяем, произошло ли расширение знака.

Это предполагает арифметику дополнения до 2, но обычно это безопасное предположение.

-1
ответ дан 5 December 2019 в 10:43
поделиться

Другой подход ко всем ответам типа «сделай это отрицательным»:

#define ISVARSIGNED(V) (~(V^V)<0)

Таким образом, нет необходимости иметь особые случаи для разных значений V, поскольку ∀ V ∈ ℤ, V ^ V = 0.

1
ответ дан 5 December 2019 в 10:43
поделиться

Это простое решение не имеет побочных эффектов, в том числе то, что ссылка на v выполняется только один раз (что важно в макросе). Мы используем расширение gcc "typeof" для получения типа v, а затем приводим -1 к этому типу:

#define IS_SIGNED_TYPE(v)   ((typeof(v))-1 <= 0)

Это <=, а не просто <, чтобы избежать предупреждений компилятора в некоторых случаях (если включено).

1
ответ дан 5 December 2019 в 10:43
поделиться

Зачем вам нужен макрос? Для этого отлично подходят шаблоны:

template <typename T>
bool is_signed(T) {
    static_assert(std::numeric_limits<T>::is_specialized, "Specialize std::numeric_limits<T>");
    return std::numeric_limits<T>::is_signed;
}

Который будет работать "из коробки" для всех основных интегральных типов. Он также завершится ошибкой во время компиляции указателей, чего, вероятно, не будет в версии, использующей только вычитание и сравнение.

РЕДАКТИРОВАТЬ : Ой, вопрос требует C. Тем не менее, шаблоны - хороший способ: P

-1
ответ дан 5 December 2019 в 10:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: