Struct as a Union member

This is a discussion on Struct as a Union member within the C++ Programming forums, part of the General Programming Boards category; This seems correct to me but my gcc compiler does not like it. I am getting an error of: Code: ...

  1. #1
    Registered User
    Join Date
    Jul 2010
    Posts
    177

    Struct as a Union member

    This seems correct to me but my gcc compiler does not like it. I am getting an error of:
    Code:
    error: 'Wordbyte' does not name a type
    I must be missing something rather simple. Here is my code.
    Code:
    #ifdef BIG_ENDIAN
    struct WordByte
    {
    	unsigned int zero:8;
    	unsigned int one:8;
    	unsigned int two:8;
    	unsigned int three:8;
    };
    #endif
    
    #ifdef LITTLE_ENDIAN
    struct WordByte
    {
    	unsigned int three:8;
    	unsigned int two:8;
    	unsigned int one:8;
    	unsigned int zero:8;
    };
    #endif
    
    union Word
    {
    	unsigned int word;
    	WordByte byte;              //<<here is where the error is pointing to.
    };
    Anyone have an idea? Thanks in advance.

  2. #2
    Registered User
    Join Date
    May 2009
    Posts
    2,521
    Did you define LITTLE_ENDIAN or BIG_ENDIAN?

    Tim S.
    "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the Universe is winning." Rick Cook

  3. #3
    Registered User
    Join Date
    Jul 2010
    Posts
    177
    Quote Originally Posted by stahta01 View Post
    Did you define LITTLE_ENDIAN or BIG_ENDIAN?

    Tim S.
    Great catch! Thanks!

  4. #4
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,457
    What are you doing? Bitfields aren't portable, and unions are generally problematic.
    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.

  5. #5
    Registered User antred's Avatar
    Join Date
    Apr 2012
    Location
    Germany
    Posts
    227
    Yeah, are you even certain an unsigned int will always be 4 bytes on any system you need to run on?

  6. #6
    Registered User
    Join Date
    Apr 2008
    Location
    Australia
    Posts
    55
    Is there more to this code?
    WordByte vs Wordbyte

  7. #7
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,046
    Some points you may find useful:
    • C (in C99) and C++ (in C++11) introduced a header called <stdint.h> or, C++-style, <cstdint>. This defines uint32_t, int16_t and other types you may find very useful. Of course, you may not want to make your code C++11 dependent (although in practice most compilers will have stdint anyway to support C); in that case I suggest you define your own. For example:
      Code:
      #include <climits>
      #if INT_MAX == 2147483647
          typedef int uint32_t;
      #else
          #error "Unknown platform, can't determine int32_t"
      #endif
      // ...
      In many projects with more sophisticated build-systems it is the build system's job to figure out details like endianness and bit-sizes, and define types appropriately. (See e.g. cmake.)
    • Although your code seems to work as it should (i.e. sizeof(WordByte) is 4), compilers are allowed to pad structures. It may not happen in this case because the struct is already a "nice" size, but certainly at higher optimization levels the compiler may well make every struct member aligned to a 16-byte boundary or whatever, and that will break your code completely. I know of one compiler that would align data structures and loops (with padding or no-ops) to 32-byte boundaries at high opt levels because of sophisticated caching requirements.
    • Often you can hide endianness issues quite easily without resorting to structs. For example, in network programming you'd use htonl() to convert "host" to "network" byte order, and ntohl() to convert the other way (networks use big endian, these functions/macros are no-ops on big-endian processors and do reversing on little endian machines). Or you may be able to inline the differences -- often the only endian-dependent code in my SDL programs is this:
      Code:
          SDL_Surface *newImage = SDL_CreateRGBSurface(
              SDL_SWSURFACE, image->w, image->h, 32,
      #if SDL_BYTEORDER == SDL_BIG_ENDIAN
              0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
      #else
              0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
      #endif
              );
    • Since BIG_ENDIAN and LITTLE_ENDIAN are supposed to be independent but at least one should be defined, you could use #else or check for an error with something like
      Code:
      #if !defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN)
          #error "Endianness not defined! Define BIG_ENDIAN or LITTLE_ENDIAN."
      #endif
    • Because you've named the members of the structure, you can't easily loop over them. You may find it more useful to inline-define shift code so you can just do something like
      Code:
      MyWordType word;
      for(std::size_t i = 0; i < sizeof(word); i ++) {
      #if BIG_ENDIAN
          dealWith((word & 0xff000000) >> 24);  // better be an unsigned type so we get logical right-shift
          word <<= CHAR_BIT;  // CHAR_BIT is from <climits>, it is almost always 8
      #else
          dealWith(word & 0xff);
          word >>= CHAR_BIT;
      #endif
      }
      That's probably not the best way, I just whipped it up. Also, I'm pretty sure you're not supposed to shift by negative values, otherwise that would make it simpler.
    Last edited by dwks; 07-08-2012 at 08:43 PM.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 02-04-2011, 09:07 AM
  2. Replies: 4
    Last Post: 09-04-2010, 09:12 AM
  3. Replies: 1
    Last Post: 05-18-2010, 04:14 AM
  4. Replies: 2
    Last Post: 03-17-2008, 12:21 AM
  5. "ambiguous access to class/struct/union member"
    By Mr_Jack in forum C++ Programming
    Replies: 1
    Last Post: 12-16-2003, 11:15 AM

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