[SOLVED] This function says duplicates something, but why?
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
int num=1; /* can be 2 */
char cmdByte;
double wordCmd;
char * pWordCmd;
int i;
pWordCmd = (char *)&wordCmd; /* sets the pWordcmd pointer
to point to the first byte
of the word cmd */
for (i = 0; i < num; i++)
{
*(UINT16 *)pWordCmd = (UINT16)cmdByte; /* converts the pWordCmd pointer
to UINT16* and writes the value of
cmdByte (also cast to uint16) to
the address pointed to by it,
so at this point the value of cmdByte
is written to the second byte of WordCmd */
pWordCmd += 2; /* advance 2 bytes */
}
so what I *BELIEVE* this code does is
if num == 1 it writes the value of cmdByte to the second byte of wordCmd
if num == 2 cmdByte is written to the 2nd and 4th byte of wordCmd
and so on
note that the cmdByte is not initialized in the function, so its value is probably some garbage data.
the casts indeed are very confusing and unnecessary.
the same functionality might be achieved using some bitwise operators and shifts.
Why is pWordCmd declared as char* and then cast to UINT16* and not declared as UIN16* in the first place?
I have no idea why would someone do this to a double. If you found this function in someone's code, read the documentation or search the code for its usage. The context should make more clear what the purpose of this function is.
In the documentation in the code, it just says it duplicates cmdByte over wordCmd.. Is there any complication when casting a cmdByte which is char into uint16? I am thinking that it may change the value because the upper byte might already contain a random value, thus extending the cmdByte into 16bit will change the original value stored in cmdByte. For example cmdByte = 0x40, when casted to 16bit, it can become 0x##40 wherein # is any value stored in the next address?
In the documentation in the code, it just says it duplicates cmdByte over wordCmd.. Is there any complication when casting a cmdByte which is char into uint16? I am thinking that it may change the value because the upper byte might already contain a random value, thus extending the cmdByte into 16bit will change the original value stored in cmdByte. For example cmdByte = 0x40, when casted to 16bit, it can become 0x##40 wherein # is any value stored in the next address?
And might have problem with endianness?
Regards,
archieval
ok. Let's declare a char variable and let it be unsigned for simplicity:
Code:
unsigned char c = 0x40;
if you cast it into UINT16, it will be
Code:
UINT16 u = (UINT16*)c;
where u = 0x0040, regardless of values in adjacent bytes of memory.
when casting a type into another type the value does not change as long as it can fit the new type. Of course, if you cast UINT16 into char, you will loose the more significant byte.
The value of c can change, however, if you cast pointers instead of values:
Code:
UINT16 u = *((UINT16*)&c);
in which case the value would change to the value at address of c and the following byte interpreted as UINT16 with the value of c being either the more significant byte or the less significant byte of the new value, depending on the endianness.
So in this case, will the function see the upper byte when cmdByte is recasted to uint16?
No. When casting from char to uint16, only the value of the char is used to compute the full value of the uint16. In a typical implementation of C, the high byte of the resulting uint16 would be filled with copies of the high bit of the char.
Anything in the upper byte of the original uint16 was lost when it was cast to char. It cannot come back when that char is cast back to uint16.
Here is a simple program to try:
Code:
#include <stdio.h>
int main()
{
unsigned short s1 = 1020;
char c1 = (char)s1;
unsigned short s2 = c1;
printf("s2 = %d\n", s2);
return 0;
}
The result is 65532.
s1 has 252 in its low byte and 3 in its high byte.
So c1 has -4 in its only bytes.
So s2 has 252 in its low byte and 255 in its high byte.
Neither the high byte of s1, nor any previous contents in the memory location that holds the high byte of s2, have any effect on the result. The value in the low byte of s1 entirely determines the value in both bytes of s2 (but does so in a way that depends on the implementation of C. The values I gave are correct for X86 and most other implementations of C).
So in this case, will the function see the upper byte when cmdByte is recasted to uint16?
let's see...
You declare cmd as uint16. That's two bytes.
Then you make a cast to char. That makes it a one byte value, the upper byte is cut off.
Next, you pass it as an argument to the wideCommand() function, which expects char as its argument. Therefore, one byte (the result of the typecast) is pushed into the stack.
When you use cmdByte inside the function and cast it to uint16 again, it reads the value from the stack. So even if it read the byte after the cmdByte argument (which it doesn't), it would not be the other byte of the cmd variable in main(), but the stored value of the base pointer or something like that.
But the cast will only change the type of the variable and not its value, if possible (there may be some issues with conversions between signed/unsigned types, though).
So the answer is no, the function won't see the upper byte of cmd, since it was discarded during the cast to char in main().
you pass it as an argument to the wideCommand() function, which expects char as its argument. Therefore, one byte (the result of the typecast) is pushed into the stack.
In 32 bit x86, 4 bytes would be pushed onto the stack. In 64 bit x86, 8 bytes would be passed (but not on the stack). The high byte discarded by the cast would likely be there in the 3 or 7 extra bytes passed. The function is supposed to ignore the value of those extra bytes.
Quote:
So even if it read the byte after the cmdByte argument (which it doesn't), it would not be the other byte of the cmd variable in main()
The correct part is that the cast from char to UINT16 doesn't read that byte. If it did, it is very possible that it would recover the high byte discarded by the previous cast.
In 32 bit x86, 4 bytes would be pushed onto the stack. In 64 bit x86, 8 bytes would be passed (but not on the stack).
even for a one-byte argument? isn't that a waste of memory? And I allways believed I save space by using char instead of int in function arguments I learn something new every day.
Then again , I'd guess x86/x86_64 architectures would be optimized for 4/8 byte arguments and the registers are 4/8 bytes anyway, so that would make sense.
Thanks for the info. Backtracking a little bit, actually cmdByte is an argument of that function.
Code:
void wideCommand (char cmdByte)
{
... /*contains the function above*/
}
And somewhere else in the file it was used as something like:
Code:
int writeCount = 128;
uint16 cmd;
int i;
for (i=0; i<count; i++)
{
cmd = i;
wideCommand((char)cmd);
}
So in this case, will the function see the upper byte when cmdByte is recasted to uint16?
Regards,
archieval
It will be similar to using cmd%256 (provided char is 8 bytes and not e.g. 7). So it will copy the least-significant-byte and 0 in place of the most-significant-byte.
Kevin Barry
Now I understand that there is really a bug on that code, wherein the upper byte is disregarded and casting it to uint16 does not bring it back. A lot of informative replies up there, thanks!
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.