Please explain code!
-
Hi I just started C++, but this code I found on the net blew me away. Could someone please help me understand, especially the lines market with a /**/. void read_data_from_bs(void *data, int bits_of_data, unsigned char *bit_stream, unsigned long & bit_offset) { int i; int n; while (bits_of_data > 0) { // <-- Colored with red by Instant Match n = bits_of_data > 8 ? 8 : bits_of_data; /**/ *(unsigned char *)data = 0; for (i = 0; i < n; i++) { if (read_bit(bit_stream, bit_offset)) { (*(unsigned char *)data) |= (1 << i); /**/ } bit_offset++ ; } data = ((unsigned char *)data) + 1; /**/ bits_of_data -= n; } }
-
Hi I just started C++, but this code I found on the net blew me away. Could someone please help me understand, especially the lines market with a /**/. void read_data_from_bs(void *data, int bits_of_data, unsigned char *bit_stream, unsigned long & bit_offset) { int i; int n; while (bits_of_data > 0) { // <-- Colored with red by Instant Match n = bits_of_data > 8 ? 8 : bits_of_data; /**/ *(unsigned char *)data = 0; for (i = 0; i < n; i++) { if (read_bit(bit_stream, bit_offset)) { (*(unsigned char *)data) |= (1 << i); /**/ } bit_offset++ ; } data = ((unsigned char *)data) + 1; /**/ bits_of_data -= n; } }
Brakanjan wrote: n = bits_of_data > 8 ? 8 : bits_of_data; /**/ First, we test if the value of bits_of_data is greater than 8 (bits_of_data > 8 ?). If yes, we store 8 into n, if no, we store the value of bits_of_data into n. These is another syntax for this:
if (bits_of_data>8) n = 8; else n = bits_of_data;
Brakanjan wrote: (*(unsigned char *)data) |= (1 << i); /**/ A little bit trickier to understand...(unsigned char*)data
means we cast the void pointer data into a pointer to unsigned char.>(*(unsigned char*)data)
means we acces to the value that is pointed by data.(1 << i)
is a bit shifting (so we put the i bit at 1 and the other are left to 0). So, with the | operator means that you leave all the bits inside your pointer the same but put the bit i to 1... Hum, hope this is clear enough because it's not easy to explain :~ Brakanjan wrote: data = ((unsigned char *)data) + 1; /**/ Means that you increment the data pointer -> so you go to the next value pointed by data. -
Hi I just started C++, but this code I found on the net blew me away. Could someone please help me understand, especially the lines market with a /**/. void read_data_from_bs(void *data, int bits_of_data, unsigned char *bit_stream, unsigned long & bit_offset) { int i; int n; while (bits_of_data > 0) { // <-- Colored with red by Instant Match n = bits_of_data > 8 ? 8 : bits_of_data; /**/ *(unsigned char *)data = 0; for (i = 0; i < n; i++) { if (read_bit(bit_stream, bit_offset)) { (*(unsigned char *)data) |= (1 << i); /**/ } bit_offset++ ; } data = ((unsigned char *)data) + 1; /**/ bits_of_data -= n; } }
Ok, there are a few things that may be confusing to a new C programmer The ? notation can be incredibly baffling if you've never seen it before - it's basically a kind of condensed if-else statement e.g.
if( n == 0 )
{
x = 42;
}
else
{
x = 0;
}could be written as
x = (n==0) ? 42 : 0;
(but it's pretty awful to have to read later, so this syntax tends not to get used very much in practice!) << and >> are "shift" operators - they perform a binary shift on a number:
1 << 8
would be the binary number 100000000 (or the decimal number 256) A line like
((unsigned char*)data)
is called a Cast - it's basically telling the compiler to treat the variabledata
as if it was of typeunsigned char*
Any good C programming book should have more details on these -- Help me! I'm turning into a grapefruit! Phoenix Paint - back from DPaint's ashes! -
Hi I just started C++, but this code I found on the net blew me away. Could someone please help me understand, especially the lines market with a /**/. void read_data_from_bs(void *data, int bits_of_data, unsigned char *bit_stream, unsigned long & bit_offset) { int i; int n; while (bits_of_data > 0) { // <-- Colored with red by Instant Match n = bits_of_data > 8 ? 8 : bits_of_data; /**/ *(unsigned char *)data = 0; for (i = 0; i < n; i++) { if (read_bit(bit_stream, bit_offset)) { (*(unsigned char *)data) |= (1 << i); /**/ } bit_offset++ ; } data = ((unsigned char *)data) + 1; /**/ bits_of_data -= n; } }
The line: { // <-- Colored with red by Instant Match Makes me suspect that this was autogenerated by some other program. I have no idea what that could be. (though it might be one of your comments and I misunderstood it) In general machine generated source code is difficult to understand. The things confusing you are rarely used C abilities. Look them up in a book, you may need them latter, but don't worry about understanding exactly what they are doing until you are more advanced. You can program for a long time without needing any of these tricky parts. I'm assuming that you are just reading this code. If you picked it because there is a reason you want to change it, then go slow. This is some tricky stuff. n = bits_of_data > 8 ? 8 : bits_of_data; You are setting n to something. Others have explained exactly what just fine. The important thing to remember when you see the "? :" operator is that n is important, not the if statement to decide what to set it too. Many programers live their entire life without using "? :", but experts know that used correctly it can make your code more readable. if else should be used far more often.
-
Ok, there are a few things that may be confusing to a new C programmer The ? notation can be incredibly baffling if you've never seen it before - it's basically a kind of condensed if-else statement e.g.
if( n == 0 )
{
x = 42;
}
else
{
x = 0;
}could be written as
x = (n==0) ? 42 : 0;
(but it's pretty awful to have to read later, so this syntax tends not to get used very much in practice!) << and >> are "shift" operators - they perform a binary shift on a number:
1 << 8
would be the binary number 100000000 (or the decimal number 256) A line like
((unsigned char*)data)
is called a Cast - it's basically telling the compiler to treat the variabledata
as if it was of typeunsigned char*
Any good C programming book should have more details on these -- Help me! I'm turning into a grapefruit! Phoenix Paint - back from DPaint's ashes! -
The line: { // <-- Colored with red by Instant Match Makes me suspect that this was autogenerated by some other program. I have no idea what that could be. (though it might be one of your comments and I misunderstood it) In general machine generated source code is difficult to understand. The things confusing you are rarely used C abilities. Look them up in a book, you may need them latter, but don't worry about understanding exactly what they are doing until you are more advanced. You can program for a long time without needing any of these tricky parts. I'm assuming that you are just reading this code. If you picked it because there is a reason you want to change it, then go slow. This is some tricky stuff. n = bits_of_data > 8 ? 8 : bits_of_data; You are setting n to something. Others have explained exactly what just fine. The important thing to remember when you see the "? :" operator is that n is important, not the if statement to decide what to set it too. Many programers live their entire life without using "? :", but experts know that used correctly it can make your code more readable. if else should be used far more often.
I came across the code while searching for a nice hex viewer/editor, so I have no idea who/what wrote it. One more thing: I see the variables accepted by the procedure is unsigned char *bit_stream and unsigned long & bit_offset, which if I remember correctly * refers to the the address and & to the value, or how should that be interpreted? how do you know which to use? tx for the help
-
I came across the code while searching for a nice hex viewer/editor, so I have no idea who/what wrote it. One more thing: I see the variables accepted by the procedure is unsigned char *bit_stream and unsigned long & bit_offset, which if I remember correctly * refers to the the address and & to the value, or how should that be interpreted? how do you know which to use? tx for the help
No in fact the * is the indirection operator. It is used to access the value pointed by a pointer. So, when you declare a pointer (int* pTest for example), it must be read like that: "the value pointed by pTest is an integer". So, it means that pTest is a pointer. The & represent the adress of something (can be a value, a char, or even a pointer...). So, when you write
int Value = 0;
, &Value represent the adress of your integer... So applying this in your case in the function, when you writeunsigned char* bit_stream
means that you are passing not the value but the pointer to an unsigned char. For your second argument, this is a little bit different: when you use the & for one of your parameter of your function, that means that this parameter is passed by reference and not by value. In other word that means implicitely that the adress of your variable is passed to the function and so, if you modify the content of it, it will be visible outside of your func (the function doesn't make a copy of the value but work directly on it). In general you use the pointer (*) when you need to pass an array, and you use the (&) when you need to get a value from your function (but without returning it with return...). Hope this is a little bit clearer -
No in fact the * is the indirection operator. It is used to access the value pointed by a pointer. So, when you declare a pointer (int* pTest for example), it must be read like that: "the value pointed by pTest is an integer". So, it means that pTest is a pointer. The & represent the adress of something (can be a value, a char, or even a pointer...). So, when you write
int Value = 0;
, &Value represent the adress of your integer... So applying this in your case in the function, when you writeunsigned char* bit_stream
means that you are passing not the value but the pointer to an unsigned char. For your second argument, this is a little bit different: when you use the & for one of your parameter of your function, that means that this parameter is passed by reference and not by value. In other word that means implicitely that the adress of your variable is passed to the function and so, if you modify the content of it, it will be visible outside of your func (the function doesn't make a copy of the value but work directly on it). In general you use the pointer (*) when you need to pass an array, and you use the (&) when you need to get a value from your function (but without returning it with return...). Hope this is a little bit clearer -
yes, I think I've got it. A pointer is used when the value of an array will (probably) be changed in the procedure, and a & is used if only a value is needed. tx indeed.
Brakanjan wrote: A pointer is used when the value of an array will (probably) be changed in the procedure Not really, it can be used also just to pass an array (even when you don't need to modify things in it). You can just pass an array by supplying the adress of its first element... And an array contains more than one value (by definition ;) ). But in essence this is it ;)