Like Tree1Likes

little endian machines

This is a discussion on little endian machines within the C++ Programming forums, part of the General Programming Boards category; Code: #include <stdio.h> int main() { union s { int i; char ch[2]; }; union s obj; obj.i=255; printf("%d %d ...

  1. #1
    Registered User
    Join Date
    Jun 2012
    Posts
    1

    little endian machines

    Code:
    #include <stdio.h>
     
    int main()
    {
            union s
           {
                int i;
                char ch[2];
           };
     
     
    union s obj;
    obj.i=255;
    printf("%d %d %d\n",obj.i,obj.ch[0],obj.ch[1]);
    
    
    }
    o/p :
    255 -1 0

    But what i expected was 255 255 0
    But How that -1 ?
    Explain please ?

    Thanks
    yogeesh serlathan
    forum4hackers.blogspot.com

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,310
    You might want to specify ch as an array of unsigned char. char can be signed or unsigned, depending on the implementation.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Jun 2012
    Posts
    1
    My first post here so Hi everybody.

    00000000 00000000 00000000 11111111 is binary of your 255, int is 32 bits long on gcc.
    With little endian this data is stored in memory in reverse byte order so you have:
    11111111 00000000 00000000 00000000
    Binary representation of -1 is 1111 1111 when variable is signed. 1111 1110 is -2 and so on.
    You can even access 2nd and 3rd element of this array:
    Code:
    union u {
            int iNum;
            char aChar[2];
        }uVar={.iNum=255};
        printf("%d, %d, %d %d %d\n", uVar.iNum, uVar.aChar[0], uVar.aChar[1], uVar.aChar[2], uVar.aChar[3]);
    ps sorry for my poor english

  4. #4
    Registered User antred's Avatar
    Join Date
    Apr 2012
    Location
    Germany
    Posts
    227
    Don't use unions like that. It'll usually work, but technically the C++ standard only permits reading the union element that was last written to. In other words, you can't write iNum and then read aChar, unless you're cool with implementation-specific behavior.


    P.S. In C++, it's not <stdio.h> but <cstdio>. All the old headers from the C standard libary can be gotten at by dropping the ".h" and prepending a "c".

    <assert.h> -> <cassert>
    <stdlib.h> -> <cstdlib>
    <stddef.h> -> <cstddef>

    etc.

    That also means that all the functions, types, etc. that used to be in the old headers are now in namespace std, so technically you should be writing std::printf() instead of just printf().
    Last edited by antred; 06-07-2012 at 05:29 AM.

  5. #5
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,413
    Quote Originally Posted by antred View Post
    That also means that all the functions, types, etc. that used to be in the old headers are now in namespace std, so technically you should be writing std:rintf() instead of just printf().
    Or... you know, just use std::cout.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,166
    Quote Originally Posted by antred View Post
    Don't use unions like that. It'll usually work, but technically the C++ standard only permits reading the union element that was last written to. In other words, you can't write iNum and then read aChar, unless you're cool with implementation-specific behavior.
    Well, yeah - but it is also a moot point.

    Every available approach for reinterpreting types (eg interpreting the memory representing an X as if it was a Y) yields some form of implementation defined or undefined behaviour.
    antred likes this.
    Right 98% of the time, and don't care about the other 3%.

  7. #7
    Registered User antred's Avatar
    Join Date
    Apr 2012
    Location
    Germany
    Posts
    227
    Quote Originally Posted by grumpy View Post
    Every available approach for reinterpreting types (eg interpreting the memory representing an X as if it was a Y) yields some form of implementation defined or undefined behaviour.
    Well, that's true I guess but then I don't see any need for that kind of stuff if all you want to do is endianness-related conversions. Oh and correct me if I'm wrong, but shouldn't the following be free of any "undefinedness"?

    Code:
    #include <iostream>
    
    bool isLittleEndian()
    {
        const unsigned char byteArray[ sizeof( unsigned short int ) ] = { 1 };
        const unsigned short int* const asUShort = reinterpret_cast < const unsigned short int* > ( byteArray );
    
        return *asUShort == static_cast < unsigned short int > ( byteArray[ 0 ] );
    }
    
    int main()
    {
        if ( isLittleEndian() )
        {
            std::cout << "little-endian\n";
        }
        else
        {
            std::cout << "big-endian\n";
        }
    }
    I don't think there is anything implementation-specific in the memory representation of unsigned, built-in integral types, or is there?

    P.S. Except of course sizeof( unsigned int ), etc. ...
    Last edited by antred; 06-07-2012 at 06:36 AM.

  8. #8
    Registered User
    Join Date
    Jun 2005
    Posts
    6,166
    Nope. The code exhibits undefined behaviour when dereferencing asUShort.
    Right 98% of the time, and don't care about the other 3%.

  9. #9
    Registered User antred's Avatar
    Join Date
    Apr 2012
    Location
    Germany
    Posts
    227
    Quote Originally Posted by grumpy View Post
    Nope. The code exhibits undefined behaviour when dereferencing asUShort.
    Seriously? Can you explain why (or point me to the relevant section in the C++ standard)?

  10. #10
    Registered User antred's Avatar
    Join Date
    Apr 2012
    Location
    Germany
    Posts
    227
    Ah well, found it. It seems you're right.


    5.2.10 Reinterpret cast
    3) The mapping performed by reinterpret_cast is implementation-defined. [Note: it might, or might
    not, produce a representation different from the original value. ]
    And no mention of any exceptions to this rule.

  11. #11
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,288
    You could write the array to file and then read it into the other array

    Okay okay, I'm just getting silly there.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  12. #12
    Registered User
    Join Date
    Jun 2005
    Posts
    6,166
    Quote Originally Posted by antred View Post
    And no mention of any exceptions to this rule.
    What you found about reinterpret_cast<> is only part of it.

    The reinterpret_cast<> has implementation defined behaviour, as you have found.

    Regardless of how the reinterpret_cast<> does any mapping, the dereferencing of asUShort (i.e. the "*asUShort") ALSO has undefined behaviour, since it treats memory containing a value of type X as if it was a value of type Y.
    Right 98% of the time, and don't care about the other 3%.

  13. #13
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,147
    has undefined behaviour
    I'm not on a machine that has the standard available so I'm compelled (by curiosity) to ask: isn't that still implemented defined instead of undefined?

    Soma

  14. #14
    Registered User
    Join Date
    Jun 2005
    Posts
    6,166
    Type conversions between values (even pointer values) give implementation-defined results.

    Dereferencing a pointer has undefined behaviour, if the pointer is of a different type from what is actually stored at that address.
    Right 98% of the time, and don't care about the other 3%.

  15. #15
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,147
    Type conversions between values (even pointer values) give implementation-defined results.
    With the exception that normal pointers must "round trip" through `void *' of course.

    Dereferencing a pointer has undefined behaviour, if the pointer is of a different type from what is actually stored at that address.
    Yes. I understood what you were saying. I wasn't arguing with you about it. I was hoping you could give the context from the standard for it.

    I wasn't looking for a quote of anything. I was just looking for the context of that portion of the standard. I can look it up myself later.

    Soma

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Little endian and Bit endian advantages and disadvantages
    By nkrao123@gmail. in forum C Programming
    Replies: 4
    Last Post: 09-11-2011, 04:40 AM
  2. Any significant Big Endian Machines?
    By abachler in forum Tech Board
    Replies: 9
    Last Post: 01-29-2009, 12:53 PM
  3. big endian-small endian problem
    By kapil1089thekin in forum C Programming
    Replies: 3
    Last Post: 05-15-2008, 06:47 PM
  4. Big Endian Little Endian Complex- Converting Characters
    By bd02eagle in forum C Programming
    Replies: 3
    Last Post: 07-11-2006, 01:01 AM
  5. Big endian/Little endian conversion
    By bonkey in forum Windows Programming
    Replies: 5
    Last Post: 09-25-2002, 02:29 PM

Tags for this Thread


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21