LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-09-2011, 01:49 AM   #1
archieval
Member
 
Registered: Apr 2007
Location: Philippines
Distribution: Kubuntu, Ubuntu, CentOS
Posts: 289

Rep: Reputation: 41
Question This function says duplicates something, but why?


Hello everyone,

I have encountered this function which is supposed to duplicate something but I don't know how exactly it goes and for what purpose.



Code:
    int num=1; /* can be 2 */
    char cmdByte;
    double wordCmd;
    char * pWordCmd;
    int i;

    pWordCmd = (char *)&wordCmd;
    for (i = 0; i < num; i++)
    {
        *(UINT16 *)pWordCmd = (UINT16)cmdByte;
        pWordCmd += 2;
    }
Can someone enlighten me on what does this function actually accomplishes because I'm quite lost on the castings? Thanks

Regards,
archieval

Last edited by archieval; 09-09-2011 at 01:52 AM.
 
Old 09-09-2011, 02:40 AM   #2
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 852

Rep: Reputation: 389Reputation: 389Reputation: 389Reputation: 389
Code:
    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.
 
Old 09-09-2011, 05:05 AM   #3
archieval
Member
 
Registered: Apr 2007
Location: Philippines
Distribution: Kubuntu, Ubuntu, CentOS
Posts: 289

Original Poster
Rep: Reputation: 41
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
 
Old 09-09-2011, 06:36 AM   #4
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 852

Rep: Reputation: 389Reputation: 389Reputation: 389Reputation: 389
Quote:
Originally Posted by archieval View Post
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.

If I'm wrong, please somebody correct me.
 
Old 09-10-2011, 07:31 AM   #5
archieval
Member
 
Registered: Apr 2007
Location: Philippines
Distribution: Kubuntu, Ubuntu, CentOS
Posts: 289

Original Poster
Rep: Reputation: 41
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
 
Old 09-10-2011, 07:58 AM   #6
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by archieval View Post
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).

Last edited by johnsfine; 09-10-2011 at 08:18 AM.
 
1 members found this post helpful.
Old 09-10-2011, 08:00 AM   #7
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 852

Rep: Reputation: 389Reputation: 389Reputation: 389Reputation: 389
Quote:
Originally Posted by archieval View Post
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().
 
Old 09-10-2011, 08:31 AM   #8
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by millgates View Post
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.
 
Old 09-10-2011, 08:47 AM   #9
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 852

Rep: Reputation: 389Reputation: 389Reputation: 389Reputation: 389
Quote:
Originally Posted by johnsfine View Post
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.
 
Old 09-10-2011, 09:25 AM   #10
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by archieval View Post
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
 
Old 09-12-2011, 03:28 AM   #11
archieval
Member
 
Registered: Apr 2007
Location: Philippines
Distribution: Kubuntu, Ubuntu, CentOS
Posts: 289

Original Poster
Rep: Reputation: 41
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!

Regards,
archieval
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Duplicates in text file. crowzie Linux - Newbie 10 07-02-2011 10:42 PM
I want to keep the duplicates not remove them! ieatbunnies Linux - Software 1 01-17-2011 12:18 PM
Evolution Duplicates Seaban Linux - Newbie 14 11-14-2010 09:50 PM
checking for duplicates fakie_flip Programming 2 09-16-2006 01:34 PM
Comparing 2 Files for Duplicates Mr_H Linux - Newbie 5 11-09-2005 12:43 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:53 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration