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 9 years ago.
Improve this question
According to text:
"In rare case of C/C++ compiler that does not perform sign extension on right shift of a negative number, the trick to shift right to divide the number fails"
Consider the following example:
unsigned int i = 0b10000000; // 128
i = i >> 1; // i equals 01000000 i.e. 64
That is the only way I know to block sign extension. Also, by adding unsigned it becomes a positive number so please correct.
Sign extension on bitwise right-shift of negative number is implementation-defined in C. It means it is up to the compiler to decide if it performs the sign propagation and the compiler documentation has to document the selected behavior.
From the C Standard:
(C99, 6.5.7) "If E1 has a signed type and a negative value, the resulting value is implementation-defined."
Among compilers, gcc always propagates the sign:
Signed `>>' acts on negative numbers by sign extension.
http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html
Related
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 2 years ago.
Improve this question
I want to merge two characters and print them via a single variable by using ASCII (refer to the image below):
[1]: https://i.stack.imgur.com/TWodP.jpg
try this if your machine is little endian
unsigned int C = (b << 8) | a;
printf("%s",&C);
otherwise if your machine is big endian try
unsigned int C = (a << 24) | (b<<16);
printf("%s",&C);
Based on my comment, but improved by Jonathan's input, I propose to do this:
int C;
C= (((unsigned char)a)<<8)|((unsigned char)b);
You have already tried the commented version to be helpful, this one is basically the same, just being robust against potentially negative values of a and b (which I considered out of scope, but Jonathan is right in being as safe as possible).
As for the explanation:
The << 8 part, a so-called bitshift left, moves a value by 8 bit towards the MSBs.
I.e. a 00000000010000001 becomes a 01000000100000000.
To be safe from negative value (see below why that is important), the value is first type-casted to unsigned char. That is the part ((unsigned char)a). Note that I tend to be generous when it comes to using (), some people do not like that. This is done for both values.
With values 'A' and 'B' we end up with
0100000100000000 and
0000000001000010.
The next part uses a bitwise OR (|), in contrast to a logical OR (||).
The result is
0100000101000010, which is what I understand to be your goal.
The importance of protecting against negative input is this. Any negative 8bit value has the MSB set and when cast to a wider data type will end up with all 8 new high bits set. This is because of the representation of negative values in integers in 2-compliment.
The final conversion to the desired wider data type is as Jonathan explains:
If you have (unsigned char)A << 8 as a term, then the unsigned char value is extended to int before the shift occurs, and the result is an int.
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 3 years ago.
Improve this question
I am trying to do left shift greater then or equal to 64, but I am not sure which DATA TYPE exists to help me out here.
I'm working on existing project, where 63 macros are already taken the next comes 64(which are my changes) for which i have to do left shift operation.
Note: I just want to understand how do i set a particular bit greater then 64bits. "I am not sure which DATA TYPE exists to help me out here".
Below code is just a sample code. We know there no data type exists greater then 64bits, but can there be any solution for this.
#include <stdio.h>
#define PEAK 64
int main()
{
unsigned long int a;
a= (1ULL << PEAK);
printf("%lu",a);
return 0;
}
main.c:8:10: warning: left shift count >= width of type [-Wshift-count-overflow]
a= (1ULL << PEAK);
^~
I just want to understand how do i set a particular bit greater then 64bits.
You can't.
Old answer:
You can do a left shift greater than or equal to 64-bits by doing exactly what you're doing.
This, of course, won't result in anything usable (either the original value, zero, or something else), and is undefined behavior, so don't do it.
If you want a data type that can do this, you're mostly out of luck. There are no guarantees that an 128-bit data type exists in C, and any compiler extensions that you may see are not portable. This may be possible with SIMD instructions but they're not portable across processors.
That said, there is unsigned __int128 in GCC and Clang that allows shifting (through emulation of wider integers). However, this isn't available in MSVC. Also note that you won't be able to print this number, so it's pretty pointless anyway.
You can shift a 64-bit unsigned type left by zero to 63 bits. Anything else will lead to undefined behaviour. The largest unsigned integer type is uintmax_t but it is usually unsigned long long on most common implementations, which is 64 bits, and the shift is equally undefined then. In practice it will result in either zero, the original value, or completely random behaviour.
Why do you think you need to do this?
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
I would like to ask if there is a difference in the result (s16Result) between
int16_t s16X, s16Y, s16Result;
s16Result = (int16_t) (s16X - s16Y);
and
int16_t s16X, s16Y, s16Result;
s16Result = (int16_t) ((uint16_t) s16X - (uint16_t) s16Y)
with s16X and s16Y having the datatype signed integer and therefore having the range -32767...32767 . Thank you.
These statements do not generally have the same behavior as defined by the C standard. Consider when s16X has the least value of its type (e.g., perhaps INT_MIN in an implementation where the int type is 16 bits, so it could be −32767) and s16Y is 2. Then, in:
s16Result = (T_S16) (s16X - s16Y)
the expression s16X - s16Y overflows—the mathematical result of −32769 is not representable in the int type, and the C standard does not define the result.
However, in:
s16Result = (T_S16) ((T_U16) s16X - (T_U16) s16Y)
the T_U16 type is presumably an unsigned 16-bit type. In this case, s16X is converted to the 16-bit type by adding or subtracting 65536, yielding 32769. s16Y retains its value of 2. Then the subtraction yields 32767. finally, this result is converted to the T_S16 type, which keeps the value 32767.
Thus, the statement with unsigned arithmetic may have a defined value in some situations where the statement with signed arithmetic does not have a value defined by the C standard.
(The statement with unsigned arithmetic still has undefined behavior if the final result is not representable in the T_S16 type, as when the final result is a number from 32768 to 65535 rather than from 0 to 32767.)
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 5 years ago.
Improve this question
Suppose you have code including:
if(i & (-1)) {}
Depending on i, what would this operation return?
There's no definitive answer to this question: it depends on the type of i and, if the operation is performed in the domain of signed type, on the signed representation used by the given platform.
For example, if i is of type unsigned int (or some larger unsigned type), the entire operation will be performed in the domain of that unsigned type. In that case -1 will get implicitly converted (by usual arithmetic conversions) to all-ones bit pattern as wide as i. The whole if will effectively become equivalent to if (i).
But with i of signed type - there's no way to say anyhting for certain.
The results of performing a bitwise operation on a negative value are implementation defined.
For example, if 2's complement representation is used for negatives, the value -1 will be represented by a sequence of all 1 bits, so performing a bitwise AND with -1 will result in the value of i.
On the other hand, if sign magnitude representation is used, only 2 bits are set in the value -1, the highest and the lowest. In that case, only the highest and lowest bits of i (after any conversions) will be set in the result.
So to summarize, you can't depend on the results without some implementation defined method of determining the representation of negative values.
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 7 years ago.
Improve this question
hi I want to do the followed task:
double time;
char array[6];
for(int index=0; index<6; index++){
array[index]=(char)(time>>(8*index));
}
but the error appears: expresion must have integral or unscoped enum
From ISO/IEC 9899:1999 (a.k.a. C99 standard):
6.5.7 Bitwise shift operators
Constraints
2 Each of the operands shall have integer type.
If you want to divide time by 2 to the power of (8*index), you can either:
Use pow() from math.h, or
Create an integer variable with value 1 << (8*index), then divide time by this variable
If you want to actually do a bit shift of the binary representation of the IEEE floating point number(1) (not that I understand why you would want to do that), you can do the following:
uint64_t x = *(uint64_t *)&time;
array[index]=(char)(x>>(8*index));
(1): Assuming your implementation uses IEEE floating point
Right shifting a float or double is almost certainly not what you meant to do, as the data representation is not one that would be affected by right shift as division by a power of 2.
You cannot use right-shifting operator for double variable.