As mentioned in some of the comments, your original approach of just casting the values should work.
if (number == (int32_t)((int8_t) number)) {
printf("%s %d\n","8", number);
} else if (number == (int32_t)((int16_t) number)){
printf("%s %d\n","16", number);
}
However, if you are required to do bit manipulations yourself (which is a bit unclear from your comments), then here are some other possible options.
Unsigned values:
You could just mask off the upper bits, by using the 'and' operation & with the maximum value for the smaller type.
If these numbers are both equal, it means the value would fit in the smaller type. If not, it means some of the upper bits were used (and got masked off) so the values would be unequal.
For instance, an 8-bit number maximum would be 11111111 or 255.
#include <stdio.h>
#include <stdint.h>
if (number == (number & UINT8_MAX)) { // Mask off the upper 24 bits
printf("%s %d\n","8", number);
} else if (number == (number & UINT16_MAX)) { // Mask off the upper 16 bits
printf("%s %d\n","16", number);
}
Signed values:
For signed values, it's a bit trickier given your restrictions. Additionally, C/C++ do not appear to define a strict way of representing negative numbers, so it may vary by compiler. However, I believe my solution below should work for both one's complement and two's complement.
#include <stdio.h>
#include <stdint.h>
// Handle negative numbers by converting them to positive value.
// We will still need to handle the minimum (i.e. most negative) value, in
// case of two's complement.
int isNegative = ((originalNumber >> 31) != 0);
int positiveNumber = isNegative ? number * -1 : number;
if ((isNegative && (number == INT8_MIN)) ||
(positiveNumber == (positiveNumber & INT8_MAX))) {
printf("%s %d\n","8", number);
} else if ((isNegative && (number== INT16_MIN)) ||
(positiveNumber == (positiveNumber & INT16_MAX))) {
printf("%s %d\n","16", number);
}