I'm learning C++ through a website - learncpp.com
and I encountered a line of code that confuses me and I'm not sure how to research it. I went back looking for an explanation on what it is and couldn't find it and I would simply like to know what to look up or what it's called so I could learn more about it.
Here's the code:
unsigned char option_viewed = 0x01;
It's referring to a bit flag. What i'm confused about is the 0x01; part. I'm assuming it's hexadecimal for one, but I'm not sure.
Thanks
When creating bit flags, people often write the literal values in hex because they are easier to read:
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
Instead of:
1, 2, 4, 8, 16, 32, 64, 128
In C++ you can represent an integer literal in 3 different bases: decimal (base 10), octal (base 8), or hexidecimal (base 16). Numbers written the "normal" way (1, 13, 405, ...) are interpreted by the compiler as base 10. Numbers starting with a 0 (01, 040, 0800, ...) are interpreted as base 8. Numbers starting with a 0x (0x1, 0x01, 0x800, ...) are interpreted as base 16.
Note that with base 16 numbers, you can have as many leading 0's after the 0x as you want. That is, 0x1, 0x01, and 0x00000001 are all just 1. The reason you might want to include more leading 0's is for alignment of the code to help with readability. As John Zwinck pointed out it's common for people to use hexidecimal to represent bit flags because every power of 2 can be written with either a 1, 2, 4, or 8 in one of the digits. So you might see something like
unsigned char red = 0x01; // 1 base 10, 00000001 base 2
unsigned char green = 0x02; // 2 base 10, 00000010 base 2
unsigned char blue = 0x04; // 4 base 10, 00000100 base 2
unsigned char yellow = 0x08; // 8 base 10, 00001000 base 2
unsigned char magenta = 0x10; // 16 base 10, 00010000 base 2
unsigned char cyan = 0x20; // 32 base 10, 00100000 base 2
unsigned char white = 0x40; // 64 base 10, 01000000 base 2
unsigned char black = 0x80; // 128 base 10, 10000000 base 2
Really each variable stores a numeric value, but because we're using powers of 2 then each value is represented by a different bit being set to 1. Since the type is an unsigned char which is only 8-bits, you'll never encounter a power larger than 255, or 0xFF hexidecimal, so two digits after the 0x is enough. If you were storing an unsigned short then you might want to write it as 0x0001 which is still just 1, but you're making it obvious that it's a 16-bit integer rather than 8-bit.
You can read more about the different numerical bases in C++ here.
Related
This was given as a past question in an exam but i'm unable to understand the result that is obtained of the last 4 printf functions. I get the conversion to hexadecimal for the first 2 but i don't really see how there are characters at
ptr[0] to ptr[3]
This is the section of code that was compiled and run.
int main(int argc, char *argv[]){
typedef unsigned char byte;
unsigned int nines = 999;
byte * ptr = (byte *) &nines;
printf ("%x\n",nines);
printf ("%x\n",nines * 0x10);
printf ("%d\n",ptr[0]);
printf ("%d\n",ptr[1]);
printf ("%d\n",ptr[2]);
printf ("%d\n",ptr[3]);
return EXIT_SUCCESS;
}
and this was the corresponding output
3e7
3e70
231
3
0
0
When you do byte * ptr = (byte *) &nines; you set the address of ptr to be the same address of nines. This has a value of 999 and in hex is 0x3e7
From the problem, I am assuming that an int has 4 bytes and this is a little endian system. i.e. bytes are stored like this.
---------------------------------
| 0xe7 | 0x03 | 0x00 | 0x00 |
---------------------------------
ptr ptr+1 ptr+2 ptr+3
So when you print them out, you get the values of 231, 3, 0 and 0 (231 is equal to 0xe7)
In the little endian system, followed by intel processors and most microcontrollers today, the least significant byte is stored first and the most significant byte is stored last.
On the other hand, we have the big endian system, followed by some older Motorola controllers and power PC's. In this the most significant byte is stored first. The output in those systems would be 0, 0, 3 and 231.
This code is platform-dependent.
Given that your platform is:
Little Endian
CHAR_BIT == 8
sizeof(int) == 4
The binary representation of 999 in memory is 11100111 00000011 00000000 00000000.
Hence the decimal representation of 999 in memory is 231 3 0 0.
As a side-note, you should bring it to the attention of your instructor at school/college/university, that since this code is platform-dependent, it is a very bad example to be given as part of an exam.
If you have an exam like this, I suggest you to change lecturer as soon as possible.
The representation of unsigned int is implementation specified, it depends on your machine for its size, endianness.
Anyway, casting from a unsigned int* to char*then read it value directly should be an undefined behavior.
In little endian like x86 machine, your unsigned int of 999 is represented as:
| 0xE7 | 0x03 | 0x00 | 0x00 |
-----------------------------
ptr ptr+1 ptr+2 ptr+3
with number between | is the value in that byte. Hence, it will be printed as:
231 3 0 0
On another machine, let's say a 32 bit, Big Endian (e.g Atmel AVR32), it will be represented as:
| 0x00 | 0x00 | 0x03 | 0xE7 |
-----------------------------
ptr ptr+1 ptr+2 ptr+3
then it will print:
0 0 3 231
In another machine, let's say a 32 bit, middle endian, it will be represented as:
| 0x03 | 0xE7 | 0x00 | 0xE0 |
-----------------------------
ptr ptr+1 ptr+2 ptr+3
then it will print:
3 231 0 0
In the older machine, let's say a 16 bit little endian machine, it is represented as:
| 0xE7 | 0x03 | xx| xx |
------------------------
ptr ptr+1 ptr+2 ptr+3
with xx is unspecified value, there is another undefined behavior.
In a 64 bit big endian machine, it is represented as:
| 0x00| 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x03 | 0xE7
-----------------------------
ptr ptr+1 ptr+2 ptr+3
it will print:
0 0 0 0
That's said, there's no exact answer for exam's question. And if yes, it still invokes undefined behavior.
Further reading about Endianness, undefined behavior
This code displays the values of each individual byte of the (assumed to be 32-bit) number nines.
nines's value is 999 in decimal, 3E7 in hexadecimal, and according to the values printed, it's stored in little-endian byte order (the "least significant" byte comes first).
It's easier to see if you convert the values to hexadecimal as well:
printf ("%x\n",ptr[0]);
printf ("%x\n",ptr[1]);
printf ("%x\n",ptr[2]);
printf ("%x\n",ptr[3]);
Which will display this:
E7
3
0
0
Also, you could interpret the decimal values this way:
231 + 3*256 + 0*65536 + 0*16777216 = 999
nines is an unsigned 32bit integer on the stack (note that it is possible for int to be 64bit wide, but it does not seem to be the case here).
ptr is a pointer, which gets initialized to the address of nines. Since it is a pointer, you can use array syntax to access the value at the address pointed to. We assume it is a little endian machine, so ptr[0] is the first (least significant) byte of nines, ptr[1] is the next, etc.
231 is then the value of the least significant byte, in hex it is 0xe7
When I type cast 433 to char I get this.
How does 433 equal to -79 while ASCII for 4 & 3 are 52 & 51 respectively, according to this table.
The decimal number 433 is 0x1b1, and is an int and is usually 32 bits longs. What happens when you cast it to a char (which usually have 8 bits) is that all but the lowest 8 bits are just thrown away, leaving you with 0xb1 which is -79 as a signed two-complement 8-bit integer.
I am having a little bit of trouble creating and using a look up table.
My code is for a microcontroller that polls an 11 bit AD converter, and based on the value updates a 7 segment display.
The way i want to write the code is to create a table with 2047 values, each value has a binary pattern attached to it representing which pins and on and off, and then having the table return that binary value as int.
I am however not sure on the syntax to create the table or calling to it.
So far i got:
int table[2048][2];
j=0;
for(i=0; i<2048; i++)
{
if(i%204==8)
{
j++;
}
if(j==0)
{
value=0x3F;
}
if(j==1)
{
value=0x06;
}
table[i][2]={i},{value};
}
the if statements keep going down to j==9, the value is the binary pattern I'm interested in returning.
Is this a smart way of approaching the problem? if the AD value returned is for example 300, how would I look it up in the table to be able to get 0x06 as the number i want?
The bits for each of the second segments are
111
6 2
6 2
777
5 3
5 3
444
So the digit 2 has bits 1, 2, 4, 5, and 7 set,and so is represented by 0x5B
That is a lot of duplicated bits, with a lot of runtime overhead, and I can't even think of an efficient way to use it. Why not a lookup table of each of the 10 decimal digits, and simply have a function assemble the result 1 decimal digit at a time?
static const unsigned char segment7digits = {
0x3F, //0 -> 00111111
0x3F, //1 -> 00000110
0x5B, //2 -> 01011011
0x4F, //3 -> 01001111
0x66, //4 -> 01100110
0x6D, //5 -> 01101101
0x7D, //6 -> 01111101
0x07, //7 -> 00000111
0x7F, //8 -> 01111111
0x6F, //9 -> 01101111
}; //these values are untested and probably have errors
int lookup_7segment_bits(int value) {
assert(value>=0 && value<=9999);
int result;
result = segment7digits[value/1%10]; //least significant decimal digit
result |= segment7digits[value/10%10]<<7;
result |= segment7digits[value/100%10]<<14;
result |= segment7digits[value/1000%10]<<21; //most significant decimal digit
return result;
};
for(unsigned int h=0; h<ImageBits.iHeight; h++)
{
for(unsigned int w=0; w<ImageBits.iWidth; w++)
{
// So in this loop - if our data isn't aligned to 4 bytes, then its been padded
// in the file so it aligns...so we check for this and skip over the padded 0's
// Note here, that the data is read in as b,g,r and not rgb as you'd think!
unsigned char r,g,b;
fread(&b, 1, 1, fp);
fread(&g, 1, 1, fp);
fread(&r, 1, 1, fp);
ImageBits.pARGB[ w + h*ImageBits.iWidth ] = (r<<16 | g<<8 | b);
}// End of for loop w
//If there are any padded bytes - we skip over them here
if( iNumPaddedBytes != 0 )
{
unsigned char skip[4];
fread(skip, 1, 4 - iNumPaddedBytes, fp);
}// End of if reading padded bytes
}// End of for loop h
I do not understand this statement and how does it store the rgb value of the pixel
ImageBits.pARGB[ w + h*ImageBits.iWidth ] = (r<<16 | g<<8 | b);
i did a read up on the << bitwise shift operator but i still do not understand how it works.Can someone help me out here.
You need to convert separate values for Red, Green and Blue into a single variable, so you push them 16 and 8 bits to the "left" respectively, so they align 8 bits for Red (begin - 16), then you get 8 bits for Green (begin - 8) and the remaining color.
Consider the following:
Red -> 00001111
Green -> 11110000
Blue -> 10101010
Then RGB -> that has 24 bits capacity would look like this initially ->
-> 00000000 00000000 00000000
(there would actually be some random rubbish but it's easier to
demonstrate like this)
Shift the Red byte 16 places to the left, so we get 00001111 00000000 00000000.
Shift the Green byte 8 places to the left, so we have 00001111 11110000 00000000.
Don't shift the Blue byte, so we have 00001111 11110000 10101010.
You could achieve a similar result with unions. Here's an ellaboration as to why we do it like this. The only way for you to access a variable is to have it's address (usually bound to a variable name, or an alias).
That means that we have an address of the first byte only and also a guarantee that if it's a variable that is 3 bytes wide, the following two bytes that are next to our addressed byte belong to us. So we can literally "push the bits" to the left (shift them) so they "flow" into the remaining bytes of the variable. We could also pointer-arithmetic a pointer there or as I've mentioned already, use a union.
Bit shifting moves the bits that make up the value along by the number you specify.
In this case it's done with colour values so that you can store multiple 1 byte components (such as RGBA which are in the range 0-255) in a single 4 byte structure such as an int
Take this byte:
00000011
which is equal to 3 in decimal. If we wanted to store the value 3 for the RGB and A channel, we would need to store this value in the int (the int being 32 bits)
R G B A
00000011 00000011 00000011 00000011
As you can see the bits are set in 4 groups of 8, and all equal the value 3, but how do you tell what the R value is when it's stored this way?
If you got rid of the G/B/A values, you'd be left with
00000011 00000000 00000000 00000000
Which still doesn't equal 3 - (in fact it's some massive number - 12884901888 I think)
In order to get this value into the last byte of the int, you need to shift the bits 24 places to the right. e.g.
12884901888 >> 24
Then the bits would look like this:
00000000 00000000 00000000 00000011
And you would have your value '3'
Basically it's just a way of moving bits around in a storage structure so that you can better manipulate the values. Putting the RGBA values into a single value is usually called stuffing the bits
let's visualize this and break it into several steps, and you'll see how simple it is.
let's say we have the ARGB 32 bit variable, that can be viewed as
int rgb = {a: 00, r: 00, g: 00, b: 00} (this is not valid code, of course, and let's leave the A out of this for now).
the value in each of these colors is 8 bit of course.
now we want to place a new value, and we have three 8 bit variables for each color:
unsigned char r = 0xff, g=0xff, b=0xff.
what we're essentially doing is taking a 32 bit variable, and then doing this:
rgb |= r << 16 (shifting the red 16 bit left. everything to right of it will remain 0)
so now we have
rgb = [a: 00, r: ff, g: 00, b: 00]
and now we do:
rgb = rgb | (g << 8) (meaning taking the existing value and OR'ing it with green shifted to its place)
so we have [a: 00, r: ff, g: ff, b: 00]
and finally...
rgb = rgb | b (meaning taking the value and ORing it with the blue 8 bits. the rest remains unchanged)
leaving us with [a: 00, r: ff, g: f, b: ff]
which represents a 32 bit (24 actually since the Alpha is irrelevant to this example) color.
I have the following code for self learning:
#include <iostream>
using namespace std;
struct bitfields{
unsigned field1: 3;
unsigned field2: 4;
unsigned int k: 4;
};
int main(){
bitfields field;
field.field1=8;
field.field2=1e7;
field.k=18;
cout<<field.k<<endl;
cout<<field.field1<<endl;
cout<<field.field2<<endl;
return 0;
}
I know that unsigned int k:4 means that k is 4 bits wide, or a maximum value of 15, and the result is the following.
2
0
1
For example, filed1 can be from 0 to 7 (included), field2 and k from 0 to 15. Why such a result? Maybe it should be all zero?
You're overflowing your fields. Let's take k as an example, it's 4 bits wide. It can hold values, as you say, from 0 to 15, in binary representation this is
0 -> 0000
1 -> 0001
2 -> 0010
3 -> 0011
...
14 -> 1110
15 -> 1111
So when you assign 18, having binary representation
18 -> 1 0010 (space added between 4th and 5th bit for clarity)
k can only hold the lower four bits, so
k = 0010 = 2.
The equivalent holds true for the rest of your fields as well.
You have these results because the assignments overflowed each bitfield.
The variable filed1 is 3 bits, but 8 takes 4 bits to present (1000). The lower three bits are all zero, so filed1 is zero.
For filed2, 17 is represented by 10001, but filed2 is only four bits. The lower four bits represent the value 1.
Finally, for k, 18 is represented by 10010, but k is only four bits. The lower four bits represent the value 2.
I hope that helps clear things up.
In C++ any unsigned type wraps around when you hit its ceiling[1]. When you define a bitfield of 4 bits, then every value you store is wrapped around too. The possible values for a bitfield of size 4 are 0-15. If you store '17', then you wrap to '1', for '18' you go one more to '2'.
Mathematically, the wrapped value is the original value modulo the number of possible values for the destination type:
For the bitfield of size 4 (2**4 possible values):
18 % 16 == 2
17 % 16 == 1
For the bitfield of size 3 (2**3 possible values):
8 % 8 == 0.
[1] This is not true for signed types, where it is undefined what happens then.