1

I would like to know if Compile (or the language) treats different a variable like:

auto unsigned int a;
a = 8;

from:

auto unsigned int a;
a = 1 << 3;

To be more precise , here a = 8 in the location of a it will be written the value 8, so there is no importance which value was there (even if there is garbage).

What I am not sure is how does exactly works in this situation a = 1 << 3.

I am sure that, inside a there is a garbage value, and if for example a == 1341 ( a garbage value ), then a = 1 << 3 results in 8.

But if 1341 in binary representation means:

00000101 00111101

then I was expecting to be 10728:

00101001 11101000.

What I am not really sure here is, does a being treated as 00000000?

In this form a gets initialized to 0 before the operation on the left is being executed?

Something like 00000000 = 1 << 3?

Where a becomes 0000 1000, or how really works in this situation?

I do understand this unsigned int a = 0, then a = a << 3 would be 8 = 0000 1000, but this is different from my Question, because here a << the operations is on a and not on 1 like in my Question.

Rizwan
  • 3,324
  • 3
  • 17
  • 38
  • I think you mat be a bit confused, and are going on a false premise. Did you consult https://en.cppreference.com/w/c/language/operator_precedence ? – StoryTeller - Unslander Monica Jan 09 '19 at 10:42
  • 1
    ", then a = 1 << 8 results in 8". Um, no. Never. – Yunnosch Jan 09 '19 at 10:43
  • 1
    Previous values does not matter for your examples. In both cases, you are assigning a constant to the variable (`8` or `1 << 8 = 256`). Previous values matter when i.e. `a =<< 2` – Jose Jan 09 '19 at 10:44
  • You seem to mix this up with `a |= (1 << 8);`, don't you? – Ctx Jan 09 '19 at 10:44
  • @Ctx Not exactly, because doing that means: `a = a | ( 1 >> 8 )` which is clearly that the operation is on the `a`. Does `a = 1 << 3` has another meaning then? –  Jan 09 '19 at 10:47
  • `a = 1 << 3` is equivalent to `a = 8` of course. – Ctx Jan 09 '19 at 10:48
  • @Ctx Moreover the operation is wrong, because `a` is not initialized here: `a |= (1 << 8);` –  Jan 09 '19 at 10:52
  • @ctx `a = 1 << 3 is equivalent to a = 8 of course`Yes, but why. How exactly works here ? –  Jan 09 '19 at 10:53
  • I have serious trouble to understand, what confuses you... `1 << 3` is `8` if you calculate it, so `a = 1 << 3` is the same as `a = 8`. I don't know what else I could explain about this. – Ctx Jan 09 '19 at 10:54
  • [What are bitwise shift (bit-shift) operators and how do they work?](https://stackoverflow.com/questions/141525/what-are-bitwise-shift-bit-shift-operators-and-how-do-they-work) does this help? `1 << 3` is equal to in base 2 to `100` which is equal in base 10 to `8`, `1 << 8` is equal to in base 2 to `100000000` which is equal in base 10 to `256`. The expression is parsed like `a = (1 << 8)` , first `1<<8` is calculated then normal assignment happens. – KamilCuk Jan 09 '19 at 10:57
  • @KamilCuk Let me put it different maybe you will understand my Question. when this `( 1 << 3 )` happens does the compiler create a mask like `0000 0000 ` and then makes operation on it, like `0000 0000 = 0000 0000 | ( 1 << 3 )`? Hope is clear now. –  Jan 09 '19 at 11:02
  • You don't know. You never know what (generic?) compiler does. See [assembly output](https://godbolt.org/z/S8blxV). The compiler may optimize `1 << 3` to 8 right away and never "create a mask" or anything. When `1 << 3` happens a compiler could generate instructions to ex. put 1 into a register, put 3 into another register, move the first register of the number of bits stored in the second register. Ot it may just store `8` in the resulting register. There is no "mask" in `1 << 3`. What is the point of `00000000 | `? Are you assuming there are only 8 bits in `int` ? – KamilCuk Jan 09 '19 at 11:05
  • @KamilCuk This is a good Answer for my Question. –  Jan 09 '19 at 11:08
  • `auto` is nothing special in C (ok, it is, I say it should be removed). It's just [storage class spcifier](https://en.cppreference.com/w/cpp/language/storage_duration). And it's __not__ the `auto` from C++. It's completely different. Moreover the auto specifier is the default for variables inside block scope. So whenever you do `main() { int x; }` it's exactly the same as `main() { auto int x; }`. – KamilCuk Jan 09 '19 at 11:13
  • In practice every compiler you are likely to ever use will calculate literal calculations at compile time. Maybe you want to add extra variable, like *unsigned volatile b=1; a=b<<8;* to force run time code generation? – hyde Jan 09 '19 at 11:14
  • @KamilCuk The `auto` keyword was there just to illustrate, that it is about a local variable. If I declare `unsigned int a;` then in `main` this: `a = a | ( 1 << 3 );` is a valid operation on `a` because `a` is initialized with `0`. But you do know what happens if `unsigned int a;` is declared in `main` followed by `a = a | ( 1 << 3 );`. –  Jan 09 '19 at 11:34
  • `int x = x + 1` is also valid code and I don't see bit operations any special here. Uninitialized variables have what is called "indeterminate value" (read as: any value) [C11 3.19.2p1](https://port70.net/~nsz/c/c11/n1570.html#3.19.2p1). You can even use it (if it isn't a trap representation, for `int` it hardly can be). But it could be anything. There even existed C code which used uninitialized variables to generate random numbers. It doesn't make the code "invalid" in itself. – KamilCuk Jan 09 '19 at 11:42
  • `1 << 3` is an _integer constant expression_. All such expressions are evaluated at compile time. The machine code generated will be the same as for `a = 8;`. This has nothing to do with the storage duration of the variable. The resulting machine code will be something that loads value 8 into a byte. – Lundin Jan 09 '19 at 14:07
  • Assignment means that the new value completely replaces the old value. It is not a partial update or anything like that – M.M Jan 10 '19 at 03:52

2 Answers2

1

Lets go step by step for the expression a = 1<<3

  1. This is a simple assignment statement where lvalue should be evaluated. So 1 << 3 will be evaluated to 8 . As Both 1 and 3 are integer literals and compiler may generate a assembly instruction somewhat like ROL 1,3 --> Rotate 1 to left by 8 and store result in accumulator.

    << has higher precedance than =.

  2. Till now we dont know where we need to store the result of above step. As a auto variable compiler may decide to store it on a stack segment. Pseudo instruction could be MOV @SP+4, A --> Move data of accumulator into a location pointed by stack pointer with offset 4.

As you said correctly a will have garbage value initially. But this does not affect the second statement.

P.S: All assembly instructions will be platform specific, Above steps are for example only.

EDIT

As pointed out by Lundin 1<<3 is integer constant expression so it will b evaluated compile time. So we may end up with a single run-time step which will be copying 8 onto stack.

Community
  • 1
  • 1
Vagish
  • 2,520
  • 19
  • 32
  • 1
    `1 << 3` is an integer constant expression so it will not get translated to ROL or any other bit shifting instruction. Because it will be calculated at compile-time, regardless of optimizer settings. The machine code will be something that writes the value 8 to a byte. – Lundin Jan 09 '19 at 14:11
0
auto unsigned int a; //a is garbage value yet
a = 1 << 8; // a assign 1<<8(256) to a. a will be 1 << 8.

if you want to setting 8th bitmask, then you have to like this:

a |= (1 << 8); //not assign, just set bitmask.

then working like your expecting.

BlackBear
  • 56
  • 4