Why do C programmers use typedefs to rename basic types?

C++C

C++ Problem Overview


So I'm far from an expert on C, but something's been bugging me about code I've been reading for a long time: can someone explain to me why C(++) programmers use typedefs to rename simple types? I understand why you would use them for structs, but what exactly is the reason for declarations I see like

typedef unsigned char uch;
typedef uch UBYTE;
typedef unsigned long ulg;
typedef unsigned int u32;
typedef signed short s16;

Is there some advantage to this that isn't clear to me (a programmer whose experience begins with Java and hasn't ventured far outside of strictly type-safe languages)? Because I can't think of any reason for it--it looks like it would just make the code less readable for people unfamiliar with the project.

Feel free to treat me like a C newbie, I honestly know very little about it and it's likely there are things I've misunderstood from the outset. ;)

C++ Solutions


Solution 1 - C++

Renaming types without changing their exposed semantics/characteristics doesn't make much sense. In your example

typedef unsigned char uch;
typedef unsigned long ulg;

belong to that category. I don't see the point, aside from making a shorter name.

But these ones

typedef uch UBYTE;
typedef unsigned int u32;
typedef signed short s16;

are a completely different story. For example, s16 stands for "signed 16 bit type". This type is not necessarily signed short. Which specific type will hide behind s16 is platform-dependent. Programmers introduce this extra level of naming indirection to simplify the support for multiple platforms. If on some other platform signed 16 bit type happens to be signed int, the programmer will only have to change one typedef definition. UBYTE apparently stands for an unsigned machine byte type, which is not necessarily unsigned char.

It's worth noting that the C99 specification already provides a standard nomenclature for integral types of specific width, like int16_t, uint32_t and so on. It probably makes more sense to stick with this standard naming convention on platforms that don't support C99.

Solution 2 - C++

This allows for portability. For example you need an unsigned 32-bit integer type. Which standard type is that? You don't know - it's implementation defined. That's why you typedef a separate type to be 32-bit unsigned integer and use the new type in your code. When you need to compile on another C implementation you just change the typedefs.

Solution 3 - C++

Sometimes it is used to reduce an unwieldy thing like volatile unsigned long to something a little more compact such as vuint32_t.

Other times it is to help with portability since types like int are not always the same on each platform. By using a typedef you can set the storage class you are interested in to the platform's closest match without changing all the source code.

Solution 4 - C++

There are many reasons to it. What I think is:

  1. Typename becomes shorter and thus code also smaller and more readable.
  2. Aliasing effect for longer structure names.
  3. Convention used in particular team/companies/style.
  4. Porting - Have same name across all OS and machine. Its native data-structure might be slightly different.

Solution 5 - C++

Following is a quote from The C Programming Language (K&R)

> Besides purely aesthetic issues, there are two main reasons for using > typedefs.

First- to parameterize a program

>
> The first is to parameterize a program against portability problems. > If typedefs are used for data types > that may be machine-dependent, only > the typedefs need change when the > program is moved.
> > One common situation is to use typedef names for various integer > quantities, then make an appropriate > set of choices of short, int, and long > for each host machine. Types like > size_t and ptrdiff_t from the standard library are examples. >

The italicized portions tells us that programmers typedef basic type for portability. If I want to make sure my program works on different platforms, using different compiler, I will try to ensure that its portability in every possible way and typedef is one of them.

When I started programming using Turbo C compiler on Windows platform, it gave us the size of int 2. When I moved to Linux platform and GCC complier, the size I get is 4. If I had developed a program using Turbo C which relied on the assertion that sizeof( int ) is always two, it would have not ported properly to my new platform.

Hope it helps.

Following quote from K&R is not related to your query but I have posted it too for the sake of completion.

Second- to provide better documentation

>The second purpose of typedefs is to provide better documentation for a > program - a type called Treeptr may be easier to understand than one declared only as a > pointer to a complicated structure.

Solution 6 - C++

Most of these patterns are bad practices that come from reading and copying existing bad code. Often they reflect misunderstandings about what C does or does not require.

  1. Is akin to #define BEGIN { except it saves some typing instead of making for more.
  2. Is akin to #define FALSE 0. If your idea of "byte" is the smallest addressable unit, char is a byte by definition. If your idea of "byte" is an octet, then either char is the octet type, or your machine has no octet type.
  3. Is really ugly shorthand for people who can't touch type...
  4. Is a mistake. It should be typedef uint32_t u32; or better yet, uint32_t should just be used directly.
  5. Is the same as 4. Replace uint32_t with int16_t.

Please put a "considered harmful" stamp on them all. typedef should be used when you really need to create a new type whose definition could change over the life cycle of your code or when the code is ported to different hardware, not because you think C would be "prettier" with different type names.

Solution 7 - C++

We use it to make it Project/platform specific, everything has a common naming convention

pname_int32, pname_uint32, pname_uint8 -- pname is project/platform/module name

And some #defines

pname_malloc, pname_strlen

It easier to read and shortens long datatypes like unsigned char to pname_uint8 also making it a convention across all modules.

When porting you need to just modify the single file , thus making porting easy.

Solution 8 - C++

To cut the long story short, you might want to do that to make your code portable (with less effort/editing). This way you don't depend to 'int', instead you are using INTEGER that can be anything you want.

Solution 9 - C++

All [|u]intN_t types, where N=8|16|32|64 and so forth, are defined per architecture in this exact manner. This is a direct consequence of the fact that the standard does not mandate that char,int,float, etc. have exactly N bits - that would be insane. Instead, the standard defines minimum and maximum values of each type as guarantees to the programmer, and in various architectures types may well exceed those boundaries. It is not an uncommon sight.

The typedefs in your post are used to defined types of a certain length, in a specific architecture. It's probably not the best choice of naming; u32 and s16 are a bit too short, in my opinion. Also, it's kind of a bad thing to expose the names ulg and uch, one could prefix them with an application specific string since they obviously will not be exposed.

Hope this helps.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMichael Louis ThalerView Question on Stackoverflow
Solution 1 - C++AnTView Answer on Stackoverflow
Solution 2 - C++sharptoothView Answer on Stackoverflow
Solution 3 - C++Amardeep AC9MFView Answer on Stackoverflow
Solution 4 - C++JackView Answer on Stackoverflow
Solution 5 - C++Andrew-DufresneView Answer on Stackoverflow
Solution 6 - C++R.. GitHub STOP HELPING ICEView Answer on Stackoverflow
Solution 7 - C++Praveen SView Answer on Stackoverflow
Solution 8 - C++houman001View Answer on Stackoverflow
Solution 9 - C++Michael FoukarakisView Answer on Stackoverflow