Please take a look at my function:
int getByte(int x, int n) {
int oneOnes = 255 << ( n << 3);
int compute = oneOnes & x;
//FIND A WAY TO RETURN CHAR (NOT INT)
char result = (compute >> (n << 3));
return result;
}
Everthing works great until the comment. That is, I start with an integer x, and I want to take only a certain subsection (specified by n). So what I did was make everything except the 8 bits I want to keep into zeros. So for example, if the input was:
1001011 10011011 00101011 01001011
And I want to keep only the 3rd group of bits (counting from the right), then the result would be:
00000000 10011011 00000000 00000000
So I've managed to do that correctly. The issue is, I need to return only the bits that I want (with the zeros cropped, as a char). Despite creating a char result and returning that, what's being returned is still the 32 bit value.
Any help? Thanks!
To be clear: For 00000000 10011011 00000000 00000000, I want only 10011011 to be returned.
Thanks!
Yes, it is not a 8-bit value as your function is declared to return the int, not a char and you are returning not the result but compute. Also, if you would like it not to be sign-propagated somewhere use unsigned char as a result type:
unsigned char getByte(int x, int n) {
int oneOnes = 255 << ( n << 3);
int compute = oneOnes & x;
//FIND A WAY TO RETURN CHAR (NOT INT)
unsigned char result = (compute >> (n << 3));
return result;
}
But the more efficient implementation is this one:
unsigned getByte(int x, int n) {
return (x >> (n << 3)) & 0xFF;
}
The basic problem is that you're trying to use signed integers to do this, but shifts of signed integers are not well defined -- whenever the bit pattern happens to be a negative value, bad things happen.
Instead, as is usually the case when doing bit manipulations, you want to use unsigned integers:
unsigned int getByte(unsigned int x, unsigned int n) {
unsigned int oneOnes = 255U << ( n << 3);
unsigned int compute = oneOnes & x;
return (compute >> (n << 3));
}
Its even easier if you do the masking AFTER the shifting, as then you don't need to shift the mask:
unsigned int getByte(unsigned int x, unsigned int n) {
return (x >> (n << 3)) & 255U;
}
Related
I have to make functions that check for overflow in integer addition, subtraction, and unsigned int addition(using only ! ~ | & ^ + >> <<). I have functions figured out for signed integer addition and subtraction, but I can't figure out how to do one for unsigned int addition.
How would I go about doing this?
Here is the code I have for the 2 functions I have completed:
int twosAddOk(int x, int y){
int z=x+y;
int a=x>>31;
int b=y>>31;
int c=z>>31;
return !!(a^b)|(!(a^c)&!(b^c));
}
int twosSubtractOK(int x, int y){
int z=x+~y+1;
return !(((x^y & x^z))>>31);
}
You can calculate the carry-out from the MSB the hard way:
int unsignedAddOk(unsigned int x, unsigned int y){
unsigned int x0=(~(1U<<31))&x; // MSB of x cleared
unsigned int y0=(~(1U<<31))&y; // MSB of y cleared
int c=(x0+y0)>>31; // Carry-in of MSB
int a=x>>31; // MSB of x
int b=y>>31; // MSB of y
return !((a&b)|(a&c)|(b&c));
}
Perhaps a solution without coding the magic number 31
// Return 1 on overflow
int unsigned_add_overflow_test(unsigned a, unsigned b) {
// Add all but the LSBits and then add 1 if both LSBits are 1
// When overflow would occur with a + b, sum's MSBit is set.
unsigned sum = (a >> 1) + (b >> 1) + (a&b&1);
// Test MSBit set
// vvv--------- All bits set
return !!(sum & ~(-1u >> 1));
// ^^^^^^^^^^ -- All bits set, except MSBit
// ^^^^^^^^^^^ -- MSBit set, rest are 0
}
Or as a one-liner
!!( ((a >> 1) + (b >> 1) + (a&b&1)) & ~(-1u >> 1)) )
I am trying to come up with a function int rotateRight (int x, int n) that rotates x to the right by n. For example,
rotateRight(0x87654321,4) = 0x76543218
This is what I have so far:
int rotateRight(int x, int n) {
int mask = (((1 << n)-1)<<(32-n));
int reserve = (int)((unsigned) (x&mask) >>(32-n));
return (x << n) | reserve;
}
However, I am forbidden to use any casting, and the allowed operations are ~ & ^ | + << and >>. Can anyone help me fix this?
Basically all you have to do is:
shift everything right by n bits using right shift: >>
shift the bits you want to rotate all the way to the left: <<
Combine the shifted right and shifted left bits with or: |
See this code for an example implementation using the function signature you require:
int rotateRight(int x, int n) {
//if n=4, x=0x12345678:
//shifted = 0x12345678 >> 4 = 0x01234567
int shifted = x >> n;
//rot_bits = (0x12345678 << 28) = 0x80000000
int rot_bits = x << (32-n);
//combined = 0x80000000 | 0x01234567 = 0x81234567
int combined = shifted | rot_bits;
return combined;
}
This implementation isn't safe though, at least not without a few guarantees - namely that x will always be positive, and n will be positive and always <= 32.
If you pass in a negative integer for shifting, it will work incorrectly since it will sign-extend the left-most bit. If you want this function to work for all integers, you should change all the types from int to unsigned int (that way no sign-extension or negative left-shifting will take place) and then modulo n by 32 (% 32). Here is a safe version of the function:
unsigned int rotateRight(unsigned int x, unsigned int n) {
//needed so you don't right shift more than int width
n %= 32;
//needed so you don't left shift more than int width
unsigned int leftshift_val = (32-n) % 32
unsigned int shifted = x >> n;
unsigned int rot_bits = x << leftshift_val;
unsigned int combined = shifted | rot_bits;
return combined;
}
And golfed down to a single line, for you minimalists:
unsigned rotr(unsigned x, unsigned n) {
return (x >> n % 32) | (x << (32-n) % 32);
}
A rotation is done with a combination of left and right shifts.
Shifting a signed integer's sign bit is a problem. Suggest converting to unsigned to perform the shift. #The Paramagnetic Croissant
An example of implementation-defined behavior is the propagation of the high-order bit when a signed integer is shifted right.
Shifting by the bit width or more is a problem. Limit actual shifting to n modulo Bit_width. OP's (...<<(32-n)); code is a problem when n == 0.
OP's example looks more like a left rotate. Will assume the function should rotate right. (0x87654321,4) --> 0x18765432. #Mark Shevchenko
An int may have a width other than 32.
#include <limits.h>
#define INT_BIT_WIDTH (sizeof (int) * CHAR_BIT)
int rotateRight(int x, int n) {
unsigned xu = x;
unsigned nu = n;
nu %= INT_BIT_WIDTH;
unsigned y = xu >> nu;
if (nu > 0) {
y |= xu << (INT_BIT_WIDTH - nu);
}
return y;
}
[Edit] as OP is limited to ~ & ^ | + << >>, use the alternate following code.
Note: This is an issue in rare cases where the width of an int is not a power of 2.
// nu %= INT_BIT_WIDTH;
nu &= INT_BIT_WIDTH - 1;
[Edit2] Thought I would form an unsigned minimalistic solution as inspired by #RPGillespie as OP cannot use %.
#include <limits.h>
#define UNS_WIDTH (sizeof (unsigned) * CHAR_BIT)
#define UNS_WIDTH_M1 (UNS_WIDTH - 1)
unsigned unsigned_rotate_right(unsigned x, unsigned n) {
return (x >> (n & UNS_WIDTH_M1)) | (x << ((UNS_WIDTH - n) & UNS_WIDTH_M1));
}
According to this explanation, rotation can be done with the following implementation.
#include<stdio.h>
#define INT_BITS 32
/*Function to left rotate n by d bits*/
int leftRotate(int n, unsigned int d)
{
/* In n<<d, last d bits are 0. To put first 3 bits of n at
last, do bitwise or of n<<d with n >>(INT_BITS - d) */
return (n << d)|(n >> (INT_BITS - d));
}
I got a problem that says: Form a character array based on an unsigned int. Array will represent that int in hexadecimal notation. Do this using bitwise operators.
So, my ideas is the following: I create a mask that has 1's for its 4 lowest value bits.
I push the bits of the given int by 4 to the right and use & on that int and mask. I repeat until (int != 0). My question is: when I get individual hex digits (packs of 4 bits), how do I convert them to a char? For example, I get:
x & mask = 1101(2) = 13(10) = D(16)
Is there a function to convert an int to hex representation, or do I have to use brute force with switch statement or whatever else?
I almost forgot, I am doing this in C :)
Here is what I mean:
#include <stdio.h>
#include <stdlib.h>
#define BLOCK 4
int main() {
unsigned int x, y, i, mask;
char a[4];
printf("Enter a positive number: ");
scanf("%u", &x);
for (i = sizeof(usnsigned int), mask = ~(~0 << 4); x; i--, x >>= BLOCK) {
y = x & mask;
a[i] = FICTIVE_NUM_TO_HEX_DIGIT(y);
}
print_array(a);
return EXIT_SUCCESS;
}
You are almost there. The simplest method to convert an integer in the range from 0 to 15 to a hexadecimal digit is to use a lookup table,
char hex_digits[] = "0123456789ABCDEF";
and index into that,
a[i] = hex_digits[y];
in your code.
Remarks:
char a[4];
is probably too small. One hexadecimal digit corresponds to four bits, so with CHAR_BIT == 8, you need up to 2*sizeof(unsigned) chars to represent the number, generally, (CHAR_BIT * sizeof(unsigned int) + 3) / 4. Depending on what print_array does, you may need to 0-terminate a.
for (i = sizeof(usnsigned int), mask = ~(~0 << 4); x; i--, x >>= BLOCK)
initialising i to sizeof(unsigned int) skips the most significant bits, i should be initialised to the last valid index into a (except for possibly the 0-terminator, then the penultimate valid index).
The mask can more simply be defined as mask = 0xF, that has the added benefit of not invoking undefined behaviour, which
mask = ~(~0 << 4)
probably does. 0 is an int, and thus ~0 is one too. On two's complement machines (that is almost everything nowadays), the value is -1, and shifting negative integers left is undefined behaviour.
char buffer[10] = {0};
int h = 17;
sprintf(buffer, "%02X", h);
Try something like this:
char hex_digits[] = "0123456789ABCDEF";
for (i = 0; i < ((sizeof(unsigned int) * CHAR_BIT + 3) / 4); i++) {
digit = (x >> (sizeof(unsigned int) * CHAR_BIT - 4)) & 0x0F;
x = x << 4;
a[i] = hex_digits[digit];
}
Ok, this is where I got:
#include <stdio.h>
#include <stdlib.h>
#define BLOCK 4
void printArray(char*, int);
int main() {
unsigned int x, mask;
int size = sizeof(unsigned int) * 2, i;
char a[size], hexDigits[] = "0123456789ABCDEF";
for (i = 0; i < size; i++)
a[i] = 0;
printf("Enter a positive number: ");
scanf("%u", &x);
for (i = size - 1, mask = ~(~0 << 4); x; i--, x >>= BLOCK) {
a[i] = hexDigits[x & mask];
}
printArray(a, size);
return EXIT_SUCCESS;
}
void printArray(char a[], int n) {
int i;
for (i = 0; i < n; i++)
printf("%c", a[i]);
putchar('\n');
}
I have compiled, it runs and it does the job correctly. I don't know... Should I be worried that this problem was a bit hard for me? At faculty, during exams, we must write our code by hand, on a piece of paper... I don't imagine I would have done this right.
Is there a better (less complicated) way to do this problem? Thank you all for help :)
I would consider the impact of potential padding bits when shifting, as shifting by anything equal to or greater than the number of value bits that exist in an integer type is undefined behaviour.
Perhaps you could terminate the string first using: array[--size] = '\0';, write the smallest nibble (hex digit) using array[--size] = "0123456789ABCDEF"[value & 0x0f], move onto the next nibble using: value >>= 4, and repeat while value > 0. When you're done, return array + size or &array[size] so that the caller knows where the hex sequence begins.
I have a function called replaceByte(x,n,c) that is to replace byte n in x with c with the following restrictions:
Bytes numbered from 0 (LSB) to 3 (MSB)
Examples: replaceByte(0x12345678,1,0xab) = 0x1234ab78
You can assume 0 <= n <= 3 and 0 <= c <= 255
Legal ops: ! ~ & ^ | + << >>
Max ops: 10
int replaceByte(int x, int n, int c) {
int shift = (c << (8 * n));
int mask = 0xff << shift;
return (mask & x) | shift;
}
but when I test it I get this error:
ERROR: Test replaceByte(-2147483648[0x80000000],0[0x0],0[0x0]) failed...
...Gives 0[0x0]. Should be -2147483648[0x80000000]
after realizing that * is not a legal operator I have finally figured it out...and if you are curious, this is what I did:
int replaceByte(int x, int n, int c) {
int mask = 0xff << (n << 3);
int shift = (c << (n << 3));
return (~mask & x) | shift;
}
Since this looks like homework I'm not going to post code, but list the steps you need to perform:
Cast c into a 32-bit number so you don't lose any bits while shifting
Next, shift c by the appropriate number of bits to the left (if n==0 no shifting, if n==1 shift by 8 etc.)
Create a 32-bit bitmask that will zero the lowest 8 bits of x, then shift this mask by the same amount as the last step
Perform bitwise AND of the shifted bitmask and x to zero out the appropriate bits of x
Perform bitwise OR (or addition) of the shifted c value and x to replace the masked bits of the latter
Ahh... You are almost there.
Just change
return (mask & x) | shift;
to
return (~mask & x) | shift;
The mask should contain all ones except for the region to be masked and not vice versa.
I am using this simple code and it works fine in gcc
#include<stdio.h>
int replaceByte(int x, int n, int c)
{
int shift = (c << (8 * n));
int mask = 0xff << shift;
return (~mask & x) | shift;
}
int main ()
{
printf("%X",replaceByte(0x80000000,0,0));
return 0;
}
Proper solution is for c = 0 as well:
int replaceByte(int x, int n, int c)
{
int shift = 8 * n;
int value = c << shift;
int mask = 0xff << shift;
return (~mask & x) | value;
}
I'm working on making a logical right shift function in C using only bitwise operators. Here's what I have:
int logical_right_shift(int x, int n)
{
int size = sizeof(int); // size of int
// arithmetic shifts to create logical shift, return 1 for true
return (x >> n) & ~(((x >> (size << 3) - 1) << (size << 3) -1)) >> (n-1);
}
This actually works for all cases except if n = 0. I've been trying to figure out a way to fix it so it will work for n = 0 as well, but I'm stuck.
int lsr(int x, int n)
{
return (int)((unsigned int)x >> n);
}
This is what you need:
int logical_right_shift(int x, int n)
{
int size = sizeof(int) * 8; // usually sizeof(int) is 4 bytes (32 bits)
return (x >> n) & ~(((0x1 << size) >> n) << 1);
}
Explain
x >> n shifts n bits right. However, if x is negative, the sign bit (left-most bit) will be copied to its right, for example:
Assume every int is 32 bits here, let
x = -2147483648 (10000000 00000000 00000000 00000000), then
x >> 1 = -1073741824 (11000000 00000000 00000000 00000000)
x >> 2 = -536870912 (11100000 00000000 00000000 00000000)
and so on.
So we need to erase out those sign extra sign bits when n is negative.
Assume n = 5 here:
0x1 << size moves 1 to the left-most position:
(10000000 00000000 00000000 00000000)
((0x1 << size) >> n) << 1 copies 1 to its n-1 neighbors:
(11111000 00000000 00000000 00000000)
~((0x1 << size) >> n) << 1! reverses all bits:
(00000111 11111111 11111111 11111111)
so we finally obtain a mask to extract what really need from x >> n:
(x >> n) & ~(((0x1 << size) >> n) << 1)
the & operation does the trick.
And the total cost of this function is 6 operations.
Just store your int in an unsigned int, and perform >> upon it.
(The sign is not extended or preserved if you use unsigned int)
http://en.wikipedia.org/wiki/Logical_shift
I think problem is in your ">> (n-1)" part. If n is 0 then left part will be shift by -1.
So,here is my solution
int logical_right_shift(int x, int n)
{
int mask = ~(-1 << n) << (32 - n);
return ~mask & ( (x >> n) | mask);
}
Derived from php's implementation of logical right shifting
function logical_right_shift( i , shift ) {
if( i & 2147483648 ) {
return ( i >> shift ) ^ ( 2147483648 >> ( shift - 1 ) );
}
return i >> shift;
}
For 32bit platforms only.
As with #Ignacio's comment, I don't know why you would want to do this (without just doing a cast to unsigned like in the other answers), but what about (assuming two's complement and binary, and that signed shifts are arithmetic):
(x >> n) + ((1 << (sizeof(int) * CHAR_BIT - n - 1)) << 1)
or:
(x >> n) ^ ((INT_MIN >> n) << 1)
Milnex's answer is great and has an awesome explanation, but the implementation unfortunately fails due to the shift by total size. Here is a working version:
int logicalShift(int x, int n) {
int totalBitsMinusOne = (sizeof(int) * 8) - 1; // usually sizeof(int) is 4 bytes (32 bits)
return (x >> n) & ~(((0x1 << totalBitsMinusOne) >> n) << 1);
}
To have 1 as the most significant bit, and all zeroes elsewhere, we need to shift 0x1 by number of bits - 1. I am submitting my own answer because my edit to the accepted answer was somehow rejected.
int logicalShift(int x, int n) {
int mask = x>>31<<31>>(n)<<1;
return mask^(x>>n);
}
Only for 32 bits