Home Swift UNIX C Assembly Go Web MCU Research Non-Tech

What is Typedef in C? How to use? What are the conveniences?

2023-04-26 | C | #Words: 1293 | 中文原版

What is Typedef?

typedef is a special feature in the C language, which is used to create new type names. You also can know from the name “type def(ine)”. typedef is similar to alias program in Unix, which adds another name to an object. typedef also makes multiple names actually correspond to same objext, but the object of typedef operation is a data type. It is to “give a nickname” to the data type. This nickname usually has the first letter capitalized and is used to indicate that it is not an underlying data type.

In C, typedef is very similar to macro #define. The difference between the two is put at the end, because you need to understand typedef first before you can understand the difference between it and macros.

How to use Typedef?

For example, in C language, there is the concept of string: an array of type char using \0 to terminate string, and a char array is actually equivalent to a pointer to char. But there is no String type in C language. Then you can use the following statements to achieve String type:

//String is a pointer, *String is equal to char. In other words, String is equal to char *
typedef char *String

You can also find nickname is not after type, rather than after typedef. (In C language, when declaring and defining variables, does variable is after type?)

At this time, you can use the following statements to declare, assign, and output “String” type data. As follows:

#include <stdio.h>

int main()
{
    typedef char *String;
    
    String p = "abc";
    printf("%s\n", p);
    return 0;
}

The output is:

abc

Again emphasizing, typedef does not create a new type, it just gives it a “nickname”. The String here is also implemented using the mechanism of the C language itself.

This method is not very common. In most cases, we wouldn’t give nickname for basic type. The names of most basic data types are already very concise and easy to understand. String is an exception. The most common thing is to use typedef to find a simpler or more understandable synonym when using a structure, and it can also make the code more concise and efficient.

For example, the following code is a very classic binary tree node structure:

struct tnode {
    char *word;
    int count; 
    struct tnode *left; 
    struct tnode *right; 
};

If you create a new node and allocate space without typedef:

struct tnode *talloc(void)
{
    return (struct tnode *) malloc(sizeof(struct tnode));
}

如果使用typedef的方法,也就是在声明结构体tnode的同时,用typedef给它起一个“外号”Treenode,如下: If you use typedef, it means to use typedef to give it a “nickname” Treenode while declaring the structure tnode:

typedef struct tnode {
	char *word;
	int count;
	Treeptr left;
	Treeptr right;
} Treenode;

Then use typedef to define *Treeptr:

typedef struct tnode *Treeptr;

In this case, creating and allocating memory is simple and can be written in a style without the pointer symbol *, as follows:

Treenode talloc(void)
{
    return (Treeptr) malloc(sizeof(struct Treenode));
}

Compared with the previous version, it is much easier to understand.

Conveniences of Typedef

The main purpose of typedef and #define is to make the code more concise, and to make the code more beautiful.

In addition, typedef has two other advantages:

  1. Parameterized programs to improve portability. This is less useful for current development. The data types of early computer were different on different computers. Such as size or name. If you use typedef, you only need to modify the typedef part when develop for different platforms. size_t and ptrdiff_t in the standard library are two examples.
  2. Make the code more understandable, because pointers in complex data types will be more difficult to understand. It will be much simpler if you use typedef. talloc in the previous section is an example.

The difference between Typedef and #define

Next, I will explain the difference between typedef and #define.

The main purpose of typedef and #define is to make the code more concise, so they both can replace text in source code. The difference is that typedef text replacement is much more powerful than macros, because typedef can be understood by the compiler.

Macros only can do simple text replacement, such as direct text replacement, simple calculations and operations. Here is a simple text replacement example:

#define MAXWORD 100

int a[MAXWORD];

When compiling, MAXWORD will be directly replaced with 100, then compile after text replacement. MAXWORD will not be treated as a variable or constant. Therefore, the scope of macro is also called the preprocessor.

By using typedef, you can implement some complex functions. For example, the following line of code creates a new type PFI, which is a pointer to a function which has two char * parameters and return value int:

typedef int (*PFI)(char *, char *);

This is very convenient when declaring some functions, such as the following function:

int strcmp(char *s, char *t)
{
    for ( ; *s == *t; s++, t++) {
        if (*s == '\0') {
            return 0;
        }
    }
    return *s - *t;
}

You can declare it like following:

PFI strcmp;

Compared to original declaration:

int strcmp(char *, char *);

Isn’t it much more concise? If there are multiple functions like about, they can be written on one line. More concise.

I hope these will help someone in need~