Is it valid on machine which is not 16 bit - c

I have been asked in an interview is it valid declaration on a machine which is not 16 bit??
Below is the declaration,
unsigned int zero = 0;
unsigned int compzero = 0xFFFF;

They are both valid declarations, yes, inasmuch as there's no syntax error.
However, if your intent is to get the complement of 0 (all bits inverted), you should use:
unsigned int zero = 0;
unsigned int compzero = ~zero;
With (for example) a 32-bit unsigned int, 0xffff and ~0 are respectively:
0000 0000 0000 0000 1111 1111 1111 1111
1111 1111 1111 1111 1111 1111 1111 1111

Yes the deceleration is valid. Think about it this way, a hex literal is no different then a decimal literal. If they wanted the result of the hex converted to decimal to be zero, then this might not be the case (depends on which system is in use and which negative-number system is in use: 1's complement, 2's complement or a simple Not operator)

Related

Attribute to a variable another variable of different type

Is this operation valid everytime ?
unsigned long long p64 = 0;
short int x = 7;
p64 = x;
So, for this example, the p64 variable will always be this one ?
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0111
which means
(p64 == 7)
I ask this question, because sometimes the bits after 0111 gets to be all 1, instead of 0. But the gcc compiler shows no warnings, so is this operation valid everytime? Do you have any solutions to convert 16 bits variables into 64 bits variables ?
When assigning to any unsigned type
.. the new type is unsigned, the value1 is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type. C17dr § 6.3.1.3 3
This means unsigned long long p64 = any_integer_type is well defined.
With short, which is signed, positive values will convert with no value change. Negatives will act like p64 = neg_short + ULLONG_MAX + 1.
As a side effect, this looks like a bit-sign extention for common short (2's complement - unpadded).
Detail: note that the conversion is not define in terms of bits.
1 with integer type .
Yes, this is valid. p64 will always have the value 7.
You should note that if x's value is negative it will be sign-extended. The value -16 for example (in binary: 1111 1111 1111 0000) will be converted to a 64-bit -16 (1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000) even though p64 is unsigned. You could avoid this by making x unsigned.

Representation of -1 due to bit overflow? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
Hey I was trying to figure out why -1 << 4 (left) shift is FFF0 after looking and reading around web I came to know that "negative" numbers have a sign bit i.e 1. So just because "-1" would mean extra 1 bit ie (33) bits which isn't possible that's why we consider -1 as 1111 1111 1111 1111 1111 1111 1111 1111
For instance :-
#include<stdio.h>
void main()
{
printf("%x",-1<<4);
}
In this example we know that –
Internal representation of -1 is all 1’s 1111 1111 1111 1111 1111 1111 1111 1111 in an 32 bit compiler.
When we bitwise shift negative number by 4 bits to left least significant 4 bits are filled with 0’s
Format specifier %x prints specified integer value as hexadecimal format
After shifting 1111 1111 1111 1111 1111 1111 1111 0000 = FFFFFFF0 will be printed.
Source for the above
http://www.c4learn.com/c-programming/c-bitwise-shift-negative-number/
First, according to the C standard, the result of a left-shift on a signed variable with a negative value is undefined. So from a strict language-lawyer perspective, the answer to the question "why does -1 << 4 result in XYZ" is "because the standard does not specify what the result should be."
What your particular compiler is really doing, though, is left-shifting the two's-complement representation of -1 as if that representation were an unsigned value. Since the 32-bit two's-complement representation of -1 is 0xFFFFFFFF (or 11111111 11111111 11111111 11111111 in binary), the result of shifting left 4 bits is 0xFFFFFFF0 or 11111111 11111111 11111111 11110000. This is the result that gets stored back in the (signed) variable, and this value is the two's-complement representation of -16. If you were to print the result as an integer (%d) you'd get -16.
This is what most real-world compilers will do, but do not rely on it, because the C standard does not require it.
First thing first, the tutorials use void main. The comp.lang.c frequently asked question 11.15 should be of interest when assessing the quality of the tutorial:
Q: The book I've been using, C Programing for the Compleat Idiot, always uses void main().
A: Perhaps its author counts himself among the target audience. Many books unaccountably use void main() in examples, and assert that it's correct. They're wrong, or they're assuming that everyone writes code for systems where it happens to work.
That said, the rest of the example is ill-advised. The C standard does not define the behaviour of signed left shift. However, a compiler implementation is allowed to define behaviour for those cases that the standard leaves purposefully open. For example GCC does define that
all signed integers have two's-complement format
<< is well-defined on negative signed numbers and >> works as if by sign extension.
Hence, -1 << 4 on GCC is guaranteed to result in -16; the bit representation of these numbers, given 32 bit int are 1111 1111 1111 1111 1111 1111 1111 1111 and 1111 1111 1111 1111 1111 1111 1111 0000 respectively.
Now, there is another undefined behaviour here: %x expects an argument that is an unsigned int, however you're passing in a signed int, with a value that is not representable in an unsigned int. However, the behaviour on GCC / with common libc's most probably is that the bytes of the signed integer are interpreted as an unsigned integer, 1111 1111 1111 1111 1111 1111 1111 0000 in binary, which in hex is FFFFFFF0.
However, a portable C program should really never
assume two's complement representation - when the representation is of importance, use unsigned int or even uint32_t
assume that the << or >> on negative numbers have a certain behaviour
use %x with signed numbers
write void main.
A portable (C99, C11, C17) program for the same use case, with defined behaviour, would be
#include <stdio.h>
#include <inttypes.h>
int main(void)
{
printf("%" PRIx32, (uint32_t)-1 << 4);
}

How does the compiler treats printing unsigned int as signed int?

I'm trying to figure out why the following code:
{
unsigned int a = 10;
a = ~a;
printf("%d\n", a);
}
a will be 00001010 to begin with, and after NOT opertaion, will transform
into 11110101.
What happens exactly when one tries to print a as signed integer, that makes
the printed result to be -11?
I thought i would end up seeing -5 maybe (according to the binary representation), but not -11.
I'll be glad to get a clarification on the matter.
2's complement notation is used to store negative numbers.
The number 10 is 0000 0000 0000 0000 0000 0000 0000 1010 in 4 byte binary.
a=~a makes the content of a as 1111 1111 1111 1111 1111 1111 1111 0101.
This number when treated as signed int will tell the compiler to
take the most significant bit as sign and rest as magnitude.
The 1 in the msb makes the number a negative number.
Hence 2's complement operation is performed on the remaining bits.
Thus 111 1111 1111 1111 1111 1111 1111 0101 becomes
000 0000 0000 0000 0000 0000 0000 1011.
This when interpreted as a decimal integer becomes -11.
When you write a = ~a; you reverse each an every bit in a, what is also called a complement to 1.
The representation of a negative number is declared as implementation dependant, meaning that different architectures could have different representation for -10 or -11.
Assuming a 32 architecture on a common processor that uses complement to 2 to represent negative numbers -1 will be represented as FFFFFFFF (hexadecimal) or 32 bits to 1.
~a will be represented as = FFFFFFF5 or in binary 1...10101 which is the representation of -11.
Nota: the first part is always the same and is not implementation dependant, ~a is FFFFFFF5 on any 32 bits architecture. It is only the second part (-11 == FFFFFFF5) that is implementation dependant. BTW it would be -10 on an architecture that would use complement to 1 to represent negative numbers.

What is the value of ~0 in C?

I want to get the values of INT_MIN and INT_MAX. I've tried ~0 and ~0 >> 1 since the leftmost bit is a sign bit but I got -1 for both of them.
It's so confused that why ~0 doesn't turn out to be 0xffffffff and ~0 >> 1 to be 0x7fffffff?
Use:
~0U >> 1
Suffix 'U' for unsigned shift behavior.
so, confused that why not ~0 turns out to be 0xffffffff?
See, what is 0 say in four bytes representation:
BIT NUMBER 31 0
▼ ▼
number bits 0000 0000 0000 0000 0000 0000 0000 0000
▲ ▲
MSB LSB
LSB - Least Significant Bit (numbered 0)
MSB - Most Significant Bit (numbered 31)
Now ~ is bitwise not operator then flips all bits in 0 as:
BIT NUMBER 31 0
▼ ▼
number bits 1111 1111 1111 1111 1111 1111 1111 1111
▲ ▲
MSB LSB
Because of MSB = 1 this representation is treated as negative number and its magnitude is find using 2'complement math that is -1.
How?
What is 1 ? it is:
number bits 0000 0000 0000 0000 0000 0000 0000 0001
▲ ▲
MSB LSB
1's complement of 1
number bits 1111 1111 1111 1111 1111 1111 1111 1110
▲ ▲
MSB LSB
2'complement? Add 1 in one's complement, that is:
number bits 1111 1111 1111 1111 1111 1111 1111 1111
▲ ▲
MSB LSB
this same as when you gets ~0 ? that is why you are getting -1 output.
Now >> shift operator?
In most implementation of C >> operator is defined as an arithmetic right shift, which preserves the sign bit MSB. So ~0 >> 1 is noting but -1 remains same.
6.5.7 [Bitwise shift operators]
5 The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.
You requirement is what is called unsigned right shift >> and the behavior you needed can be find using unsigned number that is why I suffixed U as 0U.
How to print INT_MIN and INT_MAX?
Because printing INT_MIN and INT_MAX is bit tricky(because of undefined and implementation behavior of setting MSB and bit-overflow) in C so I have written a code as follows:
#include <stdio.h>
#include<limits.h> /* include for CHAR_BIT */
int main(){
int my_int_min = 1U << ((sizeof(int) * CHAR_BIT) - 1);
int my_int_max = ~0U >> 1;
printf("INT_MIN = %d\n", my_int_min);
printf("INT_MAX = %d\n", my_int_max);
return 0;
}
See it executing #codepad, it output is:
INT_MIN = -2147483648
INT_MAX = 2147483647
How does this code work?
Note for 32-bit number range is [-2147483648, 2147483647] that is equals to [-231, 231 -1 ].
INT_MIN: -231 == -2147483648 is:
1000 0000 0000 0000 0000 0000 0000 0000
▲ ▲
MSB LSB
In expression 1U << ((sizeof(int) * CHAR_BIT) - 1), I shifts first bit the LSB(that is 1) to left most side at MSB, And because in C, setting signed bit is undefined behavior when operand is singed type so I used unsigned one 1U.
6.5.7 [Bitwise shift operators]
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2 , reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
Another point to note is I used CHAR_BIT a standard macro defined in limits.h that tells number of bits in one char in a C implementation (remember: A char is always one byte size but number of bits in one bytes can be different on different system not always guaranteed to be 8).
INT_MAX: 231 -1 == 2147483647
0111 1111 1111 1111 1111 1111 1111 1111
▲ ▲
MSB LSB
0 is of type int. So are ~0 and ~0 >> 1 because of int type promotion
~0 has all 1s in its bit pattern and it's -1 in 2's complement, which is the default representation of most modern implementations.
Right shift in C is implementation defined. But most implementations define >> as arithmetic shift when the type is signed and logical shift when the type is unsigned
Since ~0 is int, which is a signed type, ~0 >> 1 will be an arithmetic shift right. Hence the value is sign extended, cause the value to be all 1s
You need to do unsigned(~0) >> 1 or ~0U
There are no ways to get INT_MIN and INT_MAX portably because in C there are 3 different signed type implementations beside trap representations and padding bits. That's why standard libraries always define INT_MIN and INT_MAX directly with the values
~0 is -1. Every C implementation that you're likely to run into uses two's complement for signed integers, so 0xffffffff is -1 (assuming 32-bit integers). ~0 >> 1 is the equivalent of dividing -1 by 2; since we're doing integer arithmetic, the result is -1.
The value of an all bit set int depends on the sign representation that your platform has for int. This is why the macros INT_MIN and INT_MAX were invented, there is no way of computing these values in a portable way.
Based on the wikipedia article, C normally implements an arithmetic shift. That means that when you right-shift the quantity 0xffffffff, the left-most bit (sign bit) of 1 will be preserved, as you observe.
However, Wikipedia also mentions the following, so you will get a logical shift (result of 0x7fffffff) if you use the unsigned type.
The >> operator in C and C++ is not necessarily an arithmetic shift.
Usually it is only an arithmetic shift if used with a signed integer
type on its left-hand side. If it is used on an unsigned integer type
instead, it will be a logical shift.
numbers are stored in 2's compliment so ~0 is 0XFFFFFFFF which is -1 .
so FFFFFFF(1111) >>1 gives (1111)FFFFFFF = 0XFFFFFFFF = -1.
When shifting an unsigned value, the >> operator in C is a logical shift. When shifting a signed value, the >> operator is an arithmetic shift.
So , ~0U >> 1 gives (1111)FFFFFFF = 0XFFFFFFFF .
On a 32bit system, 0 is 0x00000000. ~ is the bitwise not operator, which turns every 0 bit to 1 and vice versa. Therefore, ~0 (~0x00000000) gives 0xffffffff.
This in turn is interpreted as -1 in Two's complement.

Effect of adding 0xff on a bitwise operation

I am taking a C final in a few hours, and I am going over past exams trying to make sure I understand problems I previously missed. I had the below question and I simply left it blank as I didn't know the answer and I moved on, and looking at it now I am not sure of what the answer would be... the question is;
signed short int c = 0xff00;
unsigned short int d, e;
c = c + '\xff';
d = c;
e = d >> 2;
printf("%4x, %4x, %4x\n",c,d,e);
We were asked to show what values would be printed? It is the addition of 'xff' which is throwing me off. I have solved similar problems in binary, but this hex representation is confusing me.
Could anyone explain to me what would happen here?
'\xff' is equivalent to all 1 in binary or -1 in signed int.
So initially c = 0xff00
c = c + '\xff'
In binary is
c = 1111 1111 0000 0000 + 1111 1111 1111 1111
Which yields signed short int
c = 1111 1110 1111 1111 (0xfeff)
c and d will be equal due to assignment but e is right shifted twice
e = 0011 1111 1011 1111 (0x3fbf)
I took the liberty to test this. In the code I added short int f assigned the value of c - 1.
unsigned short int c = 0xff00, f;
unsigned short int d, e;
f = c-1;
c = c + '\xff';
d = c;
e = (d >> 2);
printf("%4x, %4x, %4x, %4x\n",c,d,e,f);
And I get the same result for both c and f. f = c - 1 is not buffer overflow. c + '\xff' isn't buffer overflow either
feff, feff, 3fbf, feff
As noted by Zan Lynx, I was using unsigned short int in my sample code but the original post is signed short int. With signed int the output will have 4 extra f's.
0xff00 means the binary string 1111 1111 0000 0000.
'\xff' is a character with numeric code of 0xff and thus simply 1111 1111.
signed short int c = 0xff00;
is initializing c with out of range value (0xff00 = 65280 in decimal). This will cause to produce an erroneous result.
The first addition adds the 16-bit number, stored in c:
1111 1111 0000 0000
Plus the number that is coded as the value of the ASCII char enclosed between ' '. But in C you can specify a character as an hexadecimal code prefixed by \x like this '\xNN' where NN is a two hex digit number. The ASCII code of that character is the value of NN itself. So '\xFF' is a somewhat unusual way to say 0xFF.
The addition is to be performed using a signed short (16 bits, signed) plus a char (8 bits, signed). For it, the compiler promotes that 8-bit value to a 16-bit value, preserving the original sign by doing a sign-extension conversion.
So before the addition, 'xFF' is decoded as the 8-bit signed number 0xFF (1111 1111), which in turn is promoted to the 16-bit number 1111 1111 1111 1111 (the sign must be preserved)
The final addition is
1111 1111 0000 0000
1111 1111 1111 1111
-------------------
1111 1110 1111 1111
Which is the hexadecimal number 0xFEFF. That is the new value in variable c.
Then, there is d=c; dis unsigned short: it has the same size of a signed short, but sign is not considered here; the MSb is just another bit. As both variables have the same size, the value in d is exactly the same we had in c. That is:
d = 1111 1110 1111 1111
The difference is that any aritmetic or logical operation with this number won't take sign into account. This means, for example, that conversions that change the size of the number won't extend the sign.
e = d >> 2;
e gets the value of d shifted two bits to the right. The >> operator behaves differently depending upon the left operand is signed or not. If it is signed, the shifting is performed preserving the sign (bits entering the number from the left will have the same value as the original sign the number had before the shifting). If it is not, there will be zeroes entering from the left.
d is unsigned, so the value e gets is the result of shifting d two bits to the right, entering zeroes from the left:
e = 0011 1111 1011 1111
Which is 0x3FBF.
Finally, values printed are c,d,e:
0xFEFF, 0xFEFF, 0x3FBF
But you may see 0xFFFFFEFF as the first printed number. This is because %x expects an int, not a short. The 4 in "%4x" means: "use at least 4 digits to print the number, but if the amount of digits needed is more, use as much as needed". To print 0xFEFF as an int (32-bit int actually), it must be promoted again, and as it's signed, this is done with sign-extension. So 0xFEFF becomes 0xFFFFFEFF, which needs 8 digits to be printed, so it does.
The second and third %4x print unsigned values (d and e). These values are promoted to 32-bit ints, but this time, unsigned. So the second value is promoted to 0x0000FEFF and the third one, to 0x00003FBF. These two numbers don't actually need 8 digits to be printed, but 4, so it does so and you see only 4 digits for each number (try changing the two last %4x by %2x and you will see that the numbers are still printed with 4 digits)

Resources