Если вы знаете, что представление является 2 дополнением , то вы можете сделать:
#include <stdio.h>
#define IS_NEG(a) (!!((1 << 31) & (a)))
int main(void)
{
int n;
while(1) {
scanf("%d", &n);
printf("negative: %d\n", IS_NEG(n));
}
return 0;
}
Объяснение:
(1 << 31)
примет число1 и сдвиньте его 31 раз влево, что даст вам 1000 0000 0000 0000 0000 0000 0000 0000
.Если вы не хотите использовать сдвиг, вы также можете использовать 0x80000000
. & (a)
выполняет побитовый тест с этим большим двоичным числом.Поскольку операция И возвращает TRUE
только тогда, когда оба операнда TRUE
, из этого следует, что только если ваше число отрицательное ( в дополнительном представлении 2 * ), это вернет TRUE
. !!(...)
Это двойное отрицание объясняет тот факт, что при выполнении этого побитового И возвращаемое значение по выражению будет (1 << 31)
, если число действительно отрицательно.Таким образом, мы инвертируем это (давая нам ноль), чем инвертируем это снова (давая нам 1).Следовательно, это гарантирует, что мы получим НОЛЬ или ЕДИНИЦУ в качестве конечного результата. IS_NEG
вернет 0 для положительных чисел И 0 и вернет 1 для всех отрицательных чисел.
Поскольку MSB будет равен единице, когда число отрицательное, просто проверьте этот бит.Обратите внимание, что это будет работать только для 32-битных целых чисел (так что вы должны проверить это с sizeof(int)
. В примере возвращается 1, если число равно отрицательно , но не должно возникнуть никаких проблем, переработав его, чтобы вернуть 1 дляположительные числа.
Дайте мне знать, если это не решит проблему. Как я понимаю, вы просто хотите проверить, является ли любой заданный int
положительным / отрицательным.
Редактировать : Из комментариев я сделал программу, которая поможет вам увидеть, что происходит.
#include <stdio.h>
#define IS_NEG(a) (!!(0x80000000 & (a)))
char buf[65];
/* converts an integer @n to binary represention of @bits bits */
char *bin(int n, unsigned int bits)
{
char *s = buf;
for(bits = (1 << (bits - 1)); bits > 0; bits = bits >> 1)
/* look! double negation again! Why this? :) */
*s++ = !!(n & bits) + 48;
*s = 0;
return buf;
}
int main(void)
{
/* R will be our partial result through-out the loop */
int r, n;
while(1) {
/* get the number */
scanf("%d", &n);
/* this is the inner part of the macro
* after this, we could say IS_NEG "becomes"
* (!!(r))
*/
r = n & 0x80000000;
printf("n & 0x80000000: 0x%x\n", r);
printf(" n = %s\n", bin(n, 32));
printf(" r = %s\n", bin(r, 32));
/* now we print what R is, so you see that the bitwise AND will
* return 0x80000000 on negative numbers. It will also print
* the NEGATION of R...
*
* After the printf(), we just assign the negated value to R.
*/
printf("r = 0x%x, !r = 0x%x\n", r, !r);
r = !r;
printf(" r = %s\n", bin(r, 32));
/* After this, IS_NEG "becomes" (!(r)) */
/* In the MACRO, this would be the second negation. */
printf("r = 0x%x, !r = 0x%x\n", r, !r);
r = !r;
printf(" r = %s\n", bin(r, 32));
/* Now, if R is 0, it means the number is either ZERO or
* POSITIVE.
*
* If R is 1, then the number is negative
*/
}
return 0;
}