tags:

views:

354

answers:

5

If i have an array of short unsigned ints.

Would shifting array[k+1] left by 8 bits, put 8 bits into the lower half of array[k+1]?

Or do they simply drop off as they have gone outside of the allocated space for the element?

+3  A: 

They drop off. You can't affect the other bits this way. Try it:

#include <stdio.h>

void print_a (short * a)
{
    int i;
    for (i = 0; i < 3; i++)
        printf ("%d:%X\n", i, a[i]);
}

int main ()
{
    short a[3] = {1, -1, 3};
    print_a (a);
    a[1] <<= 8;
    print_a (a);
    return 0;
}

Output is

0:1
1:FFFFFFFF
2:3
0:1
1:FFFFFF00
2:3
Kinopiko
+3  A: 

They drop off the data type totally, not carrying over to the next array element.

If you want that sort of behavior, you have to code it yourself with something like (left shifting the entire array by four bits):

#include <stdio.h>
int main(void) {
    int i;
    unsigned short int a[4] = {0xdead,0x1234,0x5678,0xbeef};

    // Output "before" variables.

    for (i = 0; i < sizeof(a)/sizeof(*a); i++)
        printf ("before %d: 0x%04x\n", i, a[i]);
    printf ("\n");

    // This left-shifts the array by left-shifting the current
    // element and bringing in the top bit of the next element.
    // It is in a loop for all but hte last element.
    // Then it just left-shifts the last element (no more data
    // to shift into that one).

    for (i = 0; i < sizeof(a)/sizeof(*a)-1; i++)
        a[i] = (a[i] << 8) | (a[i+1] >> 8);
    a[i] = (a[i] << 8);

    // Print the "after" variables.

    for (i = 0; i < sizeof(a)/sizeof(*a); i++)
        printf ("after  %d: 0x%04x\n", i, a[i]);

    return 0;
}

This outputs:

before 0: 0xdead
before 1: 0x1234
before 2: 0x5678
before 3: 0xbeef

after  0: 0xad12
after  1: 0x3456
after  2: 0x78be
after  3: 0xef00
paxdiablo
A: 

Shifting an unsigned int left by 8 bits will fill the lower 8 bits with zeros. The top 8 bits will be discarded, it doesn't matter that they are in an array.

Incidentally, whether 8 bits is half of an unsigned int depends on your system, but on 32-bit systems, 8 bits is typically a quarter of an unsigned int.

unsigned int x = 0x12345678;
// x is 0x12345678

x <<= 8;
// x is 0x34567800
Tom
A: 

Be aware that the C definition of the int data type does not specify how many bits it contains and is system dependent. An int was originally intended to be the "natural" word size of the processor, but this isn't always so and you could find int contains 16, 32, 64 or even some odd number like 24 bits.

The only thing you are guaranteed is an unsigned int can hold all the values between 0 and UINT_MAX inclusive, where UINT_MAX must be at least 65535 - so the int types must contain at least 16 bits to hold the required range of values.

So shifting an array of integer by 8 bits will change each int individually, but be aware that this shift will not necessarily be 'half of the array'

Cruachan
+1  A: 

The way to think about this is that in C (and for most programming languages) the implementation for array[k] << 8 involves loading array[k] into a register, shifting the register, and then storing the register back into array[k]. Thus array[k+1] will remain untouched.

As an example, foo.c:

unsigned short array[5];

void main() {
  array[3] <<= 8;
}

Will generate the following instructions:

movzwl  array+6(%rip), %eax
sall    $8, %eax
movw    %ax, array+6(%rip)

This loads array[3] into %eax, modifies it, and stores it back.

Craig Trader