• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
lride

typedef a primitive type

19 posts in this topic

I often see typedefs on a primitive type. 

For example

    typedef signed   char int8;
    typedef unsigned char uint8;

    typedef signed   short int16;
    typedef unsigned short uint16;

 

What's the point of this?

0

Share this post


Link to post
Share on other sites

In this case, others have already explained the specific use here, but more generally typedefs of primitive (and non-primitive) types can be used to provide additional context about their use.

 

Primitive types convey only two things: Their size (which is platform specific), and their format (which is also platform specific, though less obviously so). But it doesn't convey a purpose or intent as to what it holds. For example, 'typedef float velocity;' and 'typedef float acceleration;' give you added information about what instances of these types (ought to) hold, that would otherwise be described only by the variable name. Now, perhaps unfortunately, typedefs aren't strong -- that is, they don't create new distinct types, they just allow you to call a type by another name -- so you can still assign a 'velocity' variable to an 'acceleration' variable or a plain old float. But the point is that it creates a logical distinction between them, even if its not enforced by the compiler.

 

Another practical advantage is that if you decide that float is insufficient for your 'velocity' or 'acceleration' types, then you can easily redefine them to be of type 'double' in only a single place, rather than hunting through every single float in your code to determine whether it holds a velocity or acceleration. In this way it can save you time and avoid subtle bugs that arise from missing one of the things you should have changed.

2

Share this post


Link to post
Share on other sites

Thank you all. I now understand it.

So a typedef header cannot be cross platform. Am I right?

0

Share this post


Link to post
Share on other sites

What is a “typedef header”?  A header full of typedef’s?

 

In any case, yes, they can be cross-platform.  That is the point.

 

 

L. Spiro

0

Share this post


Link to post
Share on other sites

Primitive types are *not* cross-platform in terms of the number of bits they contain or their representation -- IIRC, paraphrasing the standard, it says only something along the lines of "a 'char' is the smallest addressable unit of storage; a 'short' is at least as big as a 'char'; an 'int' is at least as big as a 'short'; ..." The standard doesn't say that an 'int' is exactly 32 bits (although it is in many platforms), I don't even believe it says that signed numbers must be represented as two's compliment form.

 

The idea of a typedef header like stdint.h is to define a type (the typedef) which *is* the same number of bits across many platforms, by changing the underlying primitive types appropriately on a platform-specific basis. In other words, the idea is that uint32_t is always a 32bit unsigned integer on any platform, but the underlying primitive type might be different on a 32bit x86 machine running Windows than it is on a 64bit MIPS machine running Unix.

Edited by Ravyne
0

Share this post


Link to post
Share on other sites

Thank you all. I now understand it.

So a typedef header cannot be cross platform. Am I right?

You make these headers be cross platform like:

#if defined(PLATFORM_ONE)
typedef foo int32;
#elif defined(PLATFORM_TWO)
typedef bar int32;
#else
#error "this platform not supported"'
#endif
2

Share this post


Link to post
Share on other sites

Thank you all. I now understand it.

So a typedef header cannot be cross platform. Am I right?

You make these headers be cross platform like:

 

#if defined(PLATFORM_ONE)
typedef foo int32;
#elif defined(PLATFORM_TWO)
typedef bar int32;
#else
#error "this platform not supported"'
#endif

Oh I see, I didn't think of conditional compilation

0

Share this post


Link to post
Share on other sites

Now, perhaps unfortunately, typedefs aren't strong


Ada does this. It's a nice safety rope but it can also get quite messy. Velocity equals acceleration times time? Nope, not without converting everything to a common base type. It is nice to know that you cannot mix different types by accident, but it also means you cannot mix them intentionally without writing more code. Edited by rnlf
0

Share this post


Link to post
Share on other sites

Ada does this. It's a nice safety rope but it can also get quite messy. Velocity equals acceleration times time? Nope, not without converting everything to a common base type. It is nice to know that you cannot mix different types by accident, but it also means you cannot mix them intentionally without writing more code.

 

Now I want to see a language that associates units with variables and intelligently checks that they remain valid throughout statements huh.png

0

Share this post


Link to post
Share on other sites

And if you don't mind that it will probably your compile times and might have issues with compilers where certain types don't exist, you can use black template magic to get around ifdefs and having to know the different platforms and type sizes in advance.

 

Essentially you simply stuff all signed, unsigned and floating point types into a type list and let the template recursively go through this list until it finds one with the requested sizeof. Though this is only going to be of any help if a) you can't use the (c)stdint header and b) really don't want to worry about all the potential platforms. It's also going to be messy on exotic machines, where one "byte" can be more than 8bit.

 

 
template<bool condition, class A, class B> struct SelectT { typedef A Type; };
template<class A, class B> struct SelectT<false, A, B> { typedef B Type; };
 
struct NullType;
 
template<typename A = NullType, typename B = NullType, typename C = NullType,
typename D = NullType, typename E = NullType, typename F = NullType>
struct TypeList
{
typedef A Head;
typedef TypeList<B,C,D,E,F> Tail;
};
 
template<size_t size, typename list>
struct TypeOfSize
{
typedef typename SelectT
< sizeof(typename list::Head)==size,
 typename list::Head,
 typename TypeOfSize<size, typename list::Tail>::type
>::Type type;
};
 
template<size_t size> struct TypeOfSize<size, TypeList<> > { typedef NullType type; };
 
 
 
typedef TypeList<char, short, int, long, long long> SignedType;
typedef TypeList<unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long> UnsignedType;
typedef TypeList<float, double, long double> FloatingType;
 
typedef TypeOfSize<1, SignedType>::type int8;
typedef TypeOfSize<2, SignedType>::type int16;
typedef TypeOfSize<4, SignedType>::type int32;
typedef TypeOfSize<8, SignedType>::type int64;
 
typedef TypeOfSize<1, UnsignedType>::type uint8;
typedef TypeOfSize<2, UnsignedType>::type uint16;
typedef TypeOfSize<4, UnsignedType>::type uint32;
typedef TypeOfSize<8, UnsignedType>::type uint64;
 
typedef TypeOfSize<1, FloatingType>::type float8;
typedef TypeOfSize<2, FloatingType>::type float16;
typedef TypeOfSize<4, FloatingType>::type float32;
typedef TypeOfSize<8, FloatingType>::type float64;
0

Share this post


Link to post
Share on other sites

Uuhh... nice idea. Haven't heard of this one before, nor of Boost.Units. I will definitely look into this.

 

edit: Your link is broken, but still intelligible ;-)

Edited by rnlf
0

Share this post


Link to post
Share on other sites

Ada does this. It's a nice safety rope but it can also get quite messy. Velocity equals acceleration times time? Nope, not without converting everything to a common base type. It is nice to know that you cannot mix different types by accident, but it also means you cannot mix them intentionally without writing more code.

 

Now I want to see a language that associates units with variables and intelligently checks that they remain valid throughout statements huh.png

 

As others have said, its possible to put together a pretty good system in C++ using templates, but some languages do have this kind of notion built in. Haskell and, I think, F# are two examples. I believe its called type annotation or somesuch.

1

Share this post


Link to post
Share on other sites

Now, perhaps unfortunately, typedefs aren't strong


Ada does this. It's a nice safety rope but it can also get quite messy. Velocity equals acceleration times time? Nope, not without converting everything to a common base type. It is nice to know that you cannot mix different types by accident, but it also means you cannot mix them intentionally without writing more code.

 

Yeah, it does take effort to define the proper relationships, and it can grow into a sort of combinatorial problem. The approach would be to overload operators and/or create classes that represent various units. AFAIK, this is basically what the C++ template libraries do, except that they use template magic to generate the code, perhaps type traits as well in their implementation.

 

Its a mixed bag whether strong or weak typedefs are preferable, personally I think it would have been nice to have both options: typedef as strong, typealias as weak. C/C++ typedefs are weak mostly because C's notion of type equality is rooted in its physical properties (size and format), rather than its logical ones (its intent). That's a perfectly reasonable choice for a systems language, but its unfortunate that C++ didn't introduce a way to make a new strong type other than classes.

0

Share this post


Link to post
Share on other sites

I think that thinking of "cross-platform" with these typedefs is only half the story, and possibly even the less common reason. It is of course indeed the case with the "precise size" typedefs in stdint.h.

 

For the most part, the like typedefs, are much more about code maintainability and making code forward compatible, not so much about "cross-platform".

 

Cross-platform, is something that you can give a crap about, 95% of the time. Unless you have to layout a structure so it exactly fits some given structure or you make assumptions such as sizeof(int) == sizeof(void*), you usually couldn't care less about portability. An integer is an integer, and most of the time there's no noticeable difference (overflow due to an odd too-small-size integer type is most unlikely nowadays, this is not the 1970s any more).

 

On the other hand, consider that you wrote 200,000 lines of code that assume some function (let's say posix_fadvise, or glBufferData) takes an integer argument (or, maybe even worse, returns one: say CreateWindow). Incidentially, your integers are 32bit values, but that's big enough for everyone, isn't it. Integers are the same size as a pointer, too, how lucky is that!

One day the maintainers of that function realize that hard disks can be quite a bit larger than 4GiB these days, and people actually have files larger than 4GiB, too (or vertex buffers >4GiB). So they change the function to take a 64bit integer. That's 200,000 lines of code down the drain for you. The maintainers of the other function realize that integers are not necessarily the same size as pointers (did someone say SetWindowLong?).

 

Now, the clever maintainer would have used off_t for posix_fadvise, and HWND for CreateWindow, which does not look like there is much of an advantage. Indeed it actually looks quite stupid, so many different types for only the same thing.

 

However, if one day, it is decided that one has to change the typedef, your 200,000 lines of code just need to be recompiled once, and they will work. No manual editing every occurrence needed.

Edited by samoth
1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0