Thread: A size based variable header w/o dependencies.

  1. #1
    Password:
    Join Date
    Dec 2009
    Location
    NC
    Posts
    587

    A size based variable header w/o dependencies.

    I've asked here before about how to define a variable of a specific size, and I got a good answer for most situations, but unfortunately a bad answer for mine. I'm not in a position where porting all of libc to my OS is either practical or possible, so I made a highly configurable header to serve the same purpose as stdint, but w/o including a thousand other headers. Here it is. You're free to use it. Any suggestions? Can you think of a system which uses data sizes/types this couldn't be configured for by only modifying the lines directly under "/* All values are determined from these */"?
    Code:
    #ifndef STDVAR_H
    #define STDVAR_H 1
    
    /* All values are determined from these */
    #define BYTE_BITS 8
    #define BYTE_BYTES 1
    #define WORD_BYTES BYTE_BYTES * 2
    #define DWORD_BYTES WORD_BYTES * 2
    #define QWORD_BYTES DWORD_BYTES * 2
    
    /* Define a byte sized type */
    #if WIDTH(unsigned char) == BYTE_WIDTH
    typedef byte_t unsigned char;
    #else 
    #error No byte sized type available!
    #endif
    
    /* Define a word sized type */
    #if WIDTH(unsigned wchar) == WORD_WIDTH
    typedef word_t unsigned wchar;
    #else 
    #error No word sized type available!
    #endif
    
    /* Define a dword sized type */
    #if WIDTH(unsigned int) == DWORD_WIDTH
    typedef dword_t unsigned int;
    #elif WIDTH(unsigned short) == DWORD_WIDTH
    typedef dword_t unsigned short;
    #else
    #error No dword sized type available!
    #endif
    
    /* Define a qword sized type */
    #if WIDTH(unsigned long long) == QWORD_WIDTH
    typedef qword_t unsigned long long;
    #elif WIDTH(unsigned int) == QWORD_WIDTH
    typedef qword_t unsigned int;
    #else 
    #error No qword sized type available!
    #endif
    
    #define WIDTH(type) (sizeof(type) * BYTE_BITS)
    #define MAX_VAL(type) ((1 << (WIDTH(TYPE)) - 1)
    
    #define BYTE_WIDTH BYTE_BYTES * BYTE_BITS
    #define WORD_WIDTH WORD_BYTES * BYTE_BITS
    #define DWORD_WIDTH DWORD_BYTES * BYTE_BITS
    #define QWORD_WIDTH QWORD_BYTES * BYTE_BITS
    
    
    #define MAX_BYTE ((1 << (BYTE_WIDTH) - 1)
    #define MAX_WORD ((1 << (WORD_WIDTH) - 1)
    #define MAX_DWORD ((1 << (DWORD_WIDTH) - 1)
    #define MAX_QWORD ((1 << (QWORD_WIDTH) - 1)
    
    #endif /* STDVAR_H */
    Is "typedef" correct, or should I use "#define"?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Wouldn't it be better for you to provide what <stdint.h> would have provided, given that it is not available? BYTE_BITS sounds like another name for CHAR_BIT, and BYTE_BYTES... can it ever be anything other than 1, by definition?

    Quote Originally Posted by User Name:
    Is "typedef" correct, or should I use "#define"?
    typedef should be fine.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Password:
    Join Date
    Dec 2009
    Location
    NC
    Posts
    587
    I still want to keep stdint compatibility, so reusing names in a different header that are used in libc just seems like a bad idea. I guess I could use stdint names then just have stdint include my header, but then I'd only be carrying on the tradition of dependencies.

    > BYTE_BYTES... can it ever be anything other than 1, by definition?
    I would assume not, but to keep configurability, I made it configurable anyway. Also because I don't like magic numbers, it just gives a name to that 1 that would have been in a lot of places.
    Last edited by User Name:; 07-18-2010 at 09:15 AM.

  4. #4
    Password:
    Join Date
    Dec 2009
    Location
    NC
    Posts
    587
    Also, this is a little different from stdint in that no variable has a system independent size. There is no x-bit variable mentioned. I may include that though, now that I thought of it. Thanks for kinda causing that brainstorm laserlight.

  5. #5
    Password:
    Join Date
    Dec 2009
    Location
    NC
    Posts
    587
    Uses the same guard words as gnu libc stdint w/o blocking stdint itself.
    Code:
    #ifndef SIZEVAR_H
    #define SIZEVAR_H 1
    
    /* All values are determined from these */
    #define BYTE_BITS 8
    #define BYTE_BYTES 1
    #define WORD_BYTES BYTE_BYTES * 2
    #define DWORD_BYTES WORD_BYTES * 2
    #define QWORD_BYTES DWORD_BYTES * 2
    
    /* Define a byte sized type */
    #if WIDTH(unsigned char) == BYTE_WIDTH
    typedef byte_t unsigned char;
    #else 
    #warning No byte sized type available!
    #endif
    
    /* Define a word sized type */
    #if WIDTH(unsigned wchar_t) == WORD_WIDTH
    typedef word_t unsigned wchar_t;
    #else 
    #warning No word sized type available!
    #endif
    
    /* Define a dword sized type */
    #if WIDTH(unsigned int) == DWORD_WIDTH
    typedef dword_t unsigned int;
    #elif WIDTH(unsigned short) == DWORD_WIDTH
    typedef dword_t unsigned short;
    #else
    #warning No dword sized type available!
    #endif
    
    /* Define a qword sized type */
    #if WIDTH(unsigned long long) == QWORD_WIDTH
    typedef qword_t unsigned long long;
    #elif WIDTH(unsigned int) == QWORD_WIDTH
    typedef qword_t unsigned int;
    #else 
    #warning No qword sized type available!
    #endif
    
    
    /* Define *int*_t variables */
    
    /* Signed */
    #ifndef __int8_t_defined
    #define __int8_t_defined 1
    #if WIDTH(char) == 8
    typedef int8_t char;
    #else
    #warning No int8_t!
    #endif
    #endif
    
    #ifndef __int16_t_defined
    #define __int16_t_defined 1
    #if WIDTH(wchar_t) == 16
    typedef int16_t wchar_t;
    #else
    #warning No int16_t!
    #endif
    #endif
    
    #ifndef __int32_t_defined
    #define __int32_t_defined 1
    #if WIDTH(int) == 32
    typedef int32_t int;
    #elif WIDTH(short) == 32
    typedef int32_t short;
    #else
    #warning No int32_t!
    #endif
    #endif
    
    #ifndef __int64_t_defined
    #define __int64_t_defined 1
    #if WIDTH(long long) == 64
    typedef int64_t long long;
    #elif WIDTH(int) == 64
    typedef int64_t int;
    #else
    #warning No int64_t!
    #endif
    #endif
    
    /* Usigned */
    #ifndef __uint8_t_defined
    #define __uint8_t_defined 1
    #if WIDTH(unsigned char) == 8
    typedef uint8_t unsigned char;
    #else
    #warning No uint8_t!
    #endif
    #endif
    
    #ifndef __uint16_t_defined
    #define __uint16_t_defined 1
    #if WIDTH(unsigned wchar_t) == 16
    typedef uint16_t unsigned wchar_t;
    #else
    #warning No uint16_t!
    #endif
    #endif
    
    #ifndef __uint32_t_defined
    #define __uint32_t_defined 1
    #if WIDTH(unsigned int) == 32
    typedef uint32_t unsigned int;
    #elif WIDTH(unsigned short) == 32
    typedef uint32_t unsigned short;
    #else
    #warning No uint32_t!
    #endif
    #endif
    
    #ifndef __uint64_t_defined
    #define __uint64_t_defined 1
    #if WIDTH(unsigned long long) == 64
    typedef uint64_t unsigned long long;
    #elif WIDTH(unsigned int) == 64
    typedef uint64_t unsigned int;
    #else
    #warning No uint64_t!
    #endif
    #endif
    
    
    #define WIDTH(type) (sizeof(type) * BYTE_BITS)
    #define MAX_VAL(type) ((1 << (WIDTH(TYPE)) - 1)
    
    #define BYTE_WIDTH BYTE_BYTES * BYTE_BITS
    #define WORD_WIDTH WORD_BYTES * BYTE_BITS
    #define DWORD_WIDTH DWORD_BYTES * BYTE_BITS
    #define QWORD_WIDTH QWORD_BYTES * BYTE_BITS
    
    
    #define MAX_BYTE ((1 << (BYTE_WIDTH) - 1)
    #define MAX_WORD ((1 << (WORD_WIDTH) - 1)
    #define MAX_DWORD ((1 << (DWORD_WIDTH) - 1)
    #define MAX_QWORD ((1 << (QWORD_WIDTH) - 1)
    
    #endif /* SIZEVAR_H */

  6. #6
    Registered User
    Join Date
    Dec 2008
    Location
    Black River
    Posts
    128
    This header won't work at all. The biggest reason is that `sizeof' is only available at compile time, and you're using it at preprocessing time, when it's unavailable. Secondly, you've got the typedef's wrong: it should be `typedef unsigned char byte_t', not `typedef byte_t unsigned char'. There's also a bug in the MAX_VAL macro:

    Code:
    #define MAX_VAL(type) ((1 << (WIDTH(TYPE)) - 1)
    should be:

    Code:
    #define MAX_VAL(type) ((1 << (WIDTH(type)) - 1)
    Stick close to your desks and never program a thing,
    And you all may sit in the standards commitee!

  7. #7
    Password:
    Join Date
    Dec 2009
    Location
    NC
    Posts
    587
    Thanks for pointing out the bugs, I've yet to get to a compilable version of what's using it, so I haven't taken the time to test it on a compiler(to get warning and error messages about the stuff you pointed out).

    The sizeof thing is wrong though, all the uses of sizeof would be evaluated at compile time or before. All expressions in an preprocessor if get processed before the compiler sees the code. Every other use of sizeof is switched out for it's value at compile time.

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by User Name: View Post
    The sizeof thing is wrong though, all the uses of sizeof would be evaluated at compile time or before. All expressions in an preprocessor if get processed before the compiler sees the code. Every other use of sizeof is switched out for it's value at compile time.
    I have no idea what you're trying to say here. But the point is, the preprocessor doesn't know what sizeof is. It only gets evaluated by the compiler, so your macros won't work.
    If you want/need this kind of trickery, then you will need the powerful template techniques of C++.
    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.

  9. #9
    Password:
    Join Date
    Dec 2009
    Location
    NC
    Posts
    587
    I just tried it and I get what you mean now. Sorry Ronix.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How to pass a matrix/array from main to a function
    By Inukami in forum C Programming
    Replies: 7
    Last Post: 12-09-2009, 09:03 PM
  2. char Handling, probably typical newbie stuff
    By Neolyth in forum C Programming
    Replies: 16
    Last Post: 06-21-2009, 04:05 AM
  3. way around variable array size probs?
    By crag2804 in forum C Programming
    Replies: 3
    Last Post: 09-10-2002, 05:48 PM
  4. Variable size arrays
    By crag2804 in forum C Programming
    Replies: 4
    Last Post: 09-08-2002, 06:00 PM
  5. Tab Controls - API
    By -KEN- in forum Windows Programming
    Replies: 7
    Last Post: 06-02-2002, 09:44 AM