Tips and Tricks (7)

Previous T&T

An other very surprising trick which really puzzled me!

See this very simple sketch:

uint8_t runOnce = 0x00;

void setup() {
	Serial.begin(115200);
	Serial.println("Ready...");
}  

void loop() {
	if (runOnce == 0x00) {
		runOnce = 0x01;
		for (uint8_t i = 0; i < 32; i++) {
			uint32_t j = (1 << i);
			Serial.print(i, DEC);
			Serial.print(" ");
			Serial.println(j, BIN);
		}
	}
}

gives


Ready...
0 1
1 10
2 100
3 1000
4 10000
5 100000
6 1000000
7 10000000
8 100000000
9 1000000000
10 10000000000
11 100000000000
12 1000000000000
13 10000000000000
14 100000000000000
15 11111111111111111000000000000000
16 0
17 0
18 0
19 0
20 0
21 0
22 0
23 0
24 0
25 0
26 0
27 0
28 0
29 0
30 0
31 0

What??? How come? I do not have the ultimate final explanation, but, from what I read, I understand that the shifted value (e.g. 1) has to be translated to unsigned long in order to generate the corresponding data type.

All you have to do is to cast 1 like this

uint32_t j = (1UL << i);

The result is now


Ready...
0 1
1 10
2 100
3 1000
4 10000
5 100000
6 1000000
7 10000000
8 100000000
9 1000000000
10 10000000000
11 100000000000
12 1000000000000
13 10000000000000
14 100000000000000
15 1000000000000000
16 10000000000000000
17 100000000000000000
18 1000000000000000000
19 10000000000000000000
20 100000000000000000000
21 1000000000000000000000
22 10000000000000000000000
23 100000000000000000000000
24 1000000000000000000000000
25 10000000000000000000000000
26 100000000000000000000000000
27 1000000000000000000000000000
28 10000000000000000000000000000
29 100000000000000000000000000000
30 1000000000000000000000000000000
31 10000000000000000000000000000000

as expected!

This principle applies to bytes too:

uint16_t j = (vData[j] << i);

will fail to geneate the appropriate result, use instead:

uint32_t j = (uint32_t(vData[k]) << i);

For 16 bits integers, use

uint16_t j = (1U << i);

Next T&T

Leave a Reply

You must be logged in to post a comment.