Sign in to follow this  
grill8

Questions about using data type aliases.

Recommended Posts

Hello, I have some questions about using data type aliases. I know some debate whether providing aliases is a good idea but I believe it is and plan to use them in my game engine. I would like to know if a similiar file already exists for C language data types and (if not) whether the code I list below is comprehensive for the C language (if there are data types that I am missing). Also, for C++, I know that arbitrary template classes such as std containers cannot (I believe) be typedef'd since they do not have a specific type, but does anyone know where to obtain a comprehensive C++ data type list such as std::string, std::pair etc? I would really like to provide C++ aliases for my game engine but cannot find a comprehensive list outlining the fundamental typedefable C++ data types. Thank you. The code I have for the C language data types is as follows:

// Char types --------------------------------------------------------
typedef char					    jchar;
typedef signed char				   jschar;
typedef unsigned char				   juchar;
typedef const char				   jcchar;
typedef const signed char			  jcschar;
typedef const unsigned char			  jcuchar;

// Short types -------------------------------------------------------
typedef short			   		   jint16;
typedef signed short			   	  jsint16;
typedef unsigned short				  juint16;
typedef const short				  jcint16;
typedef const signed short			 jcsint16;
typedef const unsigned short		         jcuint16;

// Int types ---------------------------------------------------------
typedef int				  	     jint;
typedef signed int				    jsint;
typedef unsigned int				    juint;
typedef const int				    jcint;
typedef const signed int		           jcsint;
typedef const unsigned int			   jcuint;

// Long types --------------------------------------------------------
typedef long			   		   jint32;
typedef signed long			          jsint32;
typedef unsigned long				  juint32;
typedef const long				  jcint32;
typedef const signed long			 jcsint32;
typedef const unsigned long		         jcuint32;

/*
// Long long types ---------------------------------------------------
typedef long long		   		   jint64;
typedef signed long long	   	          jsint64;
typedef unsigned long long			  juint64;
typedef const long long				  jcint64;
typedef const signed long long		         jcsint64;
typedef const unsigned long long                 jcuint64;
*/

// Float types -------------------------------------------------------
typedef float					   jfloat;
typedef const float				  jcfloat;

// Double types ------------------------------------------------------
typedef double					  jdouble;
typedef const double			         jcdouble;

// Long double types -------------------------------------------------
typedef long double				 jldouble;
typedef const long double                       jcldouble;

// Bool types --------------------------------------------------------
typedef bool					    jbool;
typedef const bool				   jcbool;

// Size_t types ------------------------------------------------------
typedef size_t					  jsize_t;
typedef const size_t			         jcsize_t;

// Void types --------------------------------------------------------
typedef void					    jvoid;
typedef const void				   jcvoid;



Share this post


Link to post
Share on other sites
The official standards documents for ISO C and ISO C++ are the authoritative references for any question of this type. Regarding your list of types, I'll make the following points:

For starters, you've left out all the pointer types, of which there are an infinite number. "char*", "unsigned char*", and "void*" are frequently used.

The combination "typedef const" is legal in C++, but technically illegal in standard C. ("At most one storage-class specifier may be given in the declaration specifiers in a declaration.")

You're missing at least the following standard C types: "complex", "float complex", "double complex", "long double complex", "fenv_t", "fexcept_t", "imaxdiv_t", "intmax_t", "uintmax_t", "jmp_buf", "sig_atomic_t", "va_list", "ptrdiff_t", "wchar_t", "intptr_t", "uintptr_t", "time_t", and "clock_t". (The preceding is not a complete list; consult the C standard if you wish to be thorough.)

If you want full coverage of C++ types, it gets a lot messier. Each of the types listed above can be used as the element type for any of the STL containers, such as std::vector, std::deque, std::set, std::multiset, std::map, std::multimap, std::list, std::queue, std::priority_queue, std::stack. Each of those, in turn, has its own set of iterator and const_iterator types. Bringing in the iostreams library adds the generic type basic_ios which can, again, be parameterized over any element type; more commonly, you'll use the specializations such as istream, ostream, wistream, wostream, streambuf, istringstream, ostringstream, ifstream, ofstream, etc. Again, consult the standard for a full list.

...Remind me again what any of this gains you?

Share this post


Link to post
Share on other sites
Since when has complex been a standard C type?

I can understand motives for doing away with unwieldy keyword unsigned, but I don't see what good is aliasing all types like that. Particularly strange is that you also typedef consts, why not go all the way and add static and other storage types? Also, if you need integers of specific size, you should use the stdint.h header and not assume that integers are of certain size.

Share this post


Link to post
Share on other sites
If you want a list of std::string, std::pair, and the like (which aren't C++ types, by the way), then http://www.sgi.com/tech/stl/table_of_contents.html is your best guess.

While I see typedefs generally as a very useful thing, I wouldn't use them just for using them.
Typedefs are a tool, like everything else. Used well, they will do you well, used badly, they only have adverse effects (if nothing else, they may have no useful effect but add overhead to the compiler).

For example, typedefing jint32 as long is a portability measure with good intent, except that in this particular case, it will actually make your code less portable. Mind you, sizeof(long) == 8 on most (all?) 64 bit systems, not 4.
Including <stdint.h> (or the boost equivalent, if you will) would serve you better for those standard types.

Share this post


Link to post
Share on other sites
There are several reasons why I believe typedefing basic data types is good. One reason is that it saves time during development to say type juint rather than unsigned int everywhere. In a large application, this saves both typing and code space. The other is that, say you develop on a machine that uses 32 bit ints. Then you port to a 16 bit machine and everything does not work as planned. Changing jint to jint32 fixes that with one line of code changed.
The reason that I left out the pointer types is that * is only one character and any typedefs for pointers is going to require at least one character. Also the * is a lot more clear than say a prefixed p. Same goes for references although those are purely C++.
My intent is to save on development time for both typing and code space during large application development. I have heard of people doing similiar typedefing but have no experience on the subject other than what has been presented.
As far as typedefing static variables, I originally attempted to do just that but my compiler complained saying that only one storage class for a typedef is legal. I am using VC++ 6.0.
I am under the assumption that stdint.h etc. provide mechanisms for fixed data types meaning that they do not change from machine to machine. This is fine except for that it does not save on code space or typing which is the intent of my file.

The long and short of it is that I need a way to provide consistent data types across platforms as well as efficient data type aliases to save on both code space and typing. So, I need ..... efficiently typed data type aliases which are completely portable using C and C++ languages.

I am really just trying to get a feel for this topic. I have seen it done in many large scale applications before.

Thank you again for your help and time.
Jeremy

Share this post


Link to post
Share on other sites
Hello,

In reading stdint.h a little closer I believe you guys are right that it is a better solution for portability reasons. Their variable names are consistent and short in length for typing/code space purposes. What do you think of supplementing stdint.h with your own file which typedefs const versions as well with a prefixed c to the variable types? In addition, #defines for MIN/MAX values could be added and one could create float_t, double_t, ldouble_t bool_t etc and add their #defines as well for consistency. That could provide the C data types to have a consistent naming convention, be portable across platforms and be short in typing length.

Thank you again for your help.
Jeremy

Share this post


Link to post
Share on other sites
The long and short of my concerns is how to properly handle the following ...

1) Variable sizes/default signed unsignedness etc. differ from machine to machine and how to properly handle this for all portability concerns. I believe that stdint.h (which I was not aware of) solves this.

2) How to properly save typing/code space using typedefs. I believe that typedefing const variables with a prefixed c and unsigned/signed variables with a prefixed u/s would solve this, but one would have to create their own file for this, am I right?

3) How to consistently deal with the rampant amount of differently typedefd variable types when combining implementation of different languages. I use C/C++/GDI/DirectX and Sockets. I just need to know how to properly use so many different data types that resolve to the same thing. For example there is TRUE/FALSE as well as true/false, UINT and unsigned int, DWORD as well as int. BYTE/CHAR/char etc. It just REALLY gets out of hand to have to deal with so many data types that simply resolve to the same thing. Is there a good solution for this other than figuring out which types are the same and not etc?

Thank you again for your help.
Jeremy

Share this post


Link to post
Share on other sites
Quote:
Original post by dwahler
Complex types were introduced in ISO C99, which was the first major revision since the original ANSI C standard in 1989.

Live and learn. I wonder how and if they'll merge that with std::complex<>.

1. Personally I would not typedef const. The keyword pops up nicely in syntax highlight, serving a purpose as documentation. Some more advanced editors may even highlight instances of const variables differently. Further, int and const int are basically the same type. I think that int and cint give more the appearance of two completely distinct types. I really don't think that having to type 'onst' and pressing space is that much more work. ('unsigned' is too much work)

2. I'd pick consistent typing in all of your own code, only using the other kind of types when dealing with a particular API that has them. Mostly, no special type conversion code is needed. For example, TRUE/FALSE are usually (int)1 and 0. They convert nicely to bool and back.

Share this post


Link to post
Share on other sites
Quote:
Original post by grill8
There are several reasons why I believe typedefing basic data types is good. One reason is that it saves time during development to say type juint rather than unsigned int everywhere. In a large application, this saves both typing and code space. The other is that, say you develop on a machine that uses 32 bit ints. Then you port to a 16 bit machine and everything does not work as planned. Changing jint to jint32 fixes that with one line of code changed.
The reason that I left out the pointer types is that * is only one character and any typedefs for pointers is going to require at least one character. Also the * is a lot more clear than say a prefixed p. Same goes for references although those are purely C++.
My intent is to save on development time for both typing and code space during large application development. I have heard of people doing similiar typedefing but have no experience on the subject other than what has been presented.
As far as typedefing static variables, I originally attempted to do just that but my compiler complained saying that only one storage class for a typedef is legal. I am using VC++ 6.0.
I am under the assumption that stdint.h etc. provide mechanisms for fixed data types meaning that they do not change from machine to machine. This is fine except for that it does not save on code space or typing which is the intent of my file.

The long and short of it is that I need a way to provide consistent data types across platforms as well as efficient data type aliases to save on both code space and typing. So, I need ..... efficiently typed data type aliases which are completely portable using C and C++ languages.

I am really just trying to get a feel for this topic. I have seen it done in many large scale applications before.

Thank you again for your help and time.
Jeremy


The whole argument of "it saves me typing" is probably the worst I ever heard. If it's such a pain to type "unsigned" every time it is perhaps time to invest in a decent IDE (ctrl+space in VS2005 even for keywords).
Perhaps this aliasing even requires more typing... I use a normal "int" (jint32) far more often than "unsigned int" (juint32). So the 3 extra characters I have to write extra for your int alias will only pay off if I use less than three times as many ints than unsigned ints (9 chars for "unsigned " (including space) vs 3 for you alias).
And then I didn't even count the keystrokes you need for typing #include "yourTypes.h" every time.
See how silly this whole argument becomes when you think about it.


The argument of being cross-(hardware)platform is the one I mostly heard for typedefing the built in types. And even then it's arguable if you really need it. For example, if you port your application from a 32 bit environment to a 16 bit environment how often are your algorithms dependent on the fact something is either 32 or 16 bits?
Even better... if you want to port your stuff to a 16 bit platform (which is highly unlikely), you'll probably have more work rewriting your algorithms to fixed point than the size of your datatypes.

From 32 to 64 bits platforms is a more likely port, and even there you may argue that there are very few places where you are dependent on data size. The only places I can think of right now is reading/writing binary files and networking. Those are pretty isolated. The rest, internally, what depends on the number of bits?
But even if you are so incredibly worried about being cross platform, you're still not robust against little/big endian platforms.


Then another argument NOT to do it: If I were to develop for you engine (or use a lib of yours) I don't want to drag in your special type names. It contaminates my code.
Also, VS2005 highlights primitive types with a blue color, which is nice. You're going to break that with your types.



But in the end, every argument here is a matter of personal taste. There is no technical reason (as far as I know) to alias the data types, nor to not do it. Just pick whatever feels right.

Share this post


Link to post
Share on other sites
Quote:
Original post by grill8
I am using VC++ 6.0.
Any particular reason you're using a pre-standard compiler and IDE that's now a decade old rather than one of the brand new versions that are freely available? You mention that you're planning to use data type aliases, which implies that you've not yet started your project - why the out-of-date and broken technology?

Share this post


Link to post
Share on other sites
No, this type of aliases is pointless - it doesn't do anything.

If you abstracted type sizes (uint32_t, or similar) to server some purpose (ensuring data sizes for serialization, then it makes sense.

But simply renaming the types into something (why j?) doesn't do anything.

Quote:
be typedef'd since they do not have a specific type


They are very specifically typed. Each container defines types such as value_type, size_type, and so on. That's the types that should be used for generic programming.

Share this post


Link to post
Share on other sites
IMHO, creating an alias for a base type *just* to rename the base type is irrelevant, except for adding another batch of things to maintain and remember.

I would rather create a typedef for a functionnal reason. e.g :

typedef double Coordinate


but not

typedef double MyOwnDoubleTypeDefinitionForTheWin


What you intend to do is like naming a css class (to going back to my speciality) "BoldRedText" instead of "WarningMessage" and is considered bad practice.


OpenGL do such things, and I ended up just ignoring those aliases and use plain C types instead.





Share this post


Link to post
Share on other sites
Quote:
3) How to consistently deal with the rampant amount of differently typedefd variable types when combining implementation of different languages. I use C/C++/GDI/DirectX and Sockets. I just need to know how to properly use so many different data types that resolve to the same thing. For example there is TRUE/FALSE as well as true/false, UINT and unsigned int, DWORD as well as int. BYTE/CHAR/char etc. It just REALLY gets out of hand to have to deal with so many data types that simply resolve to the same thing. Is there a good solution for this other than figuring out which types are the same and not etc?

You're only making this problem worse, and with no gain to yourself.

There are valid reasons for aliasing types -- one of the biggest bonuses for library code is it provides you a mechanism to guarantee data type sizes at compile time, which can be extremely useful for some libraries.

The problem with simply 'renaming' them is that you add no extra information or functionality, and in this specific case of using your types versus the 'other' renamed types, can actually break your code if you're working on cross-platform stuff (your renamed type may not sync up with the library type on all platforms; I've seen it happen and it's rather unpleasant to track down).

Renaming types for renaming's sake is generally not useful and only smacks of unwarranted code homogenization. When in Rome, use the types defined by the Romans.

Share this post


Link to post
Share on other sites
Quote:
Original post by jpetrie

Renaming types for renaming's sake is generally not useful and only smacks of unwarranted code homogenization. When in Rome, use the types defined by the Romans.


<offtopic>


void main() {
const uintVIII_t char;
intXXXII_t a;
intXXXII_t b;

const intVIII * text = "Hello Rome!";

std::cin >> a >> b;
std::cout << text << a << b;

// in Rome, you can't return 0;
return I;
}


On second thought, in Rome, type aliasing would be justified.

</offtopic>

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