[C language] Keyword analysis (2) typedef and #define and their differences

typedef keyword

The typedef keyword is the abbreviation of type define. I read a book before and said that maybe this keyword should be called typerename. I personally agree with this view. Because this keyword just redefines an existing type . Convenient aliases that do not create new data types. To put it bluntly, typedef is type renaming.
In practical applications, typedef mainly has the following applications:

1 Define new names for basic data types (two functions)

①Make data type names concise:

typedef unsigned int UINT;//unsigened int略显冗余,所以重新命名为UNIT (此处结尾有分号;)
int main()
{
    
    
	UNIT a; //这里使用了自己重新命名的UNIT
	return 0;
}

②Code portability:
Through C language code portability, it can run on different platforms and use typedef to define platform-independent types. If the user's program code uses floating point types, and the maximum precision supported by different platforms is different, you can use typedef to directly redefine a floating point type, and modify its definition when the code is running on different platforms.

//平台一:支持double的精度
typedef double decimal
//平台二:支持float的精度
typedef float decimal   //在不同平台修改decimal的内容即可 

2. Rename the array type a new name

typedef int arr[10];//这里arr就是一个整型数组类型名,当用户需要定义包含10个元素的整型数组时
int main()
{
    
    
	arr my_arr; //这里就等同于int my_arr[10]
	return 0;
}

3. Rename the pointer type a new name

//一个经典问题:
//下面的p1,p2是什么类型
int main()
{
    
    
	int* p1,p2; //此时int旁边的*属于p1,并不属于p2,所以p1为整形指针,p2为整型
}
//现在换一种情况
typedef int * ptr_t; //typedef对int*整体进行了重命名
int main()
{
    
    
	ptr_t p1,p2; //此时ptr_t属于p1,也属于p2,所以p1,p2都是整型指针!!!
}
  1. Rename a custom data type (structure, enumeration, union, etc.)
typedef struct node
{
    
    
	char a;
	int data;
}stu,*pstu 
//这里在定义结构体数据类型时,利用typedef定义了两个类型,stu和pstu分别为普通变量类型和指向结构的指针类型。

Summary : Although typedef can make some basic data types and custom data types simpler, it cannot be used in large quantities. Excessive use of typedef may increase the complexity of the code. When defining a large number of complex custom type aliases, it can become more difficult to understand the code. So use it appropriately!

define keyword

Before explaining this keyword, I want to show you a slightly humorous code.
Insert image description here

#define is called a macro definition command, which is a type of C language preprocessing command.
Macro definition uses an identifier to represent a string. When the identifier appears in the code, it will be replaced with the specified string.
Because it is just Simple replacement, the preprocessor does not check it. If there is an error, it can only be found when compiling the source program that has been expanded by the macro.

Grammar form: #define name stuff (no semicolon at the end; if a semicolon is added, the semicolon will be replaced together)
# indicates that this is a preprocessing command, and all preprocessing commands start with #. name is a type of identifier, and the naming rules are the same as variables. stuff can be numbers, expressions, if statements, functions, etc.

Scope: When writing, it must be outside the function. The scope is from the macro definition command to the end of the source program (or use #undef).
If the name of the macro definition appears within quotation marks, the preprocessor will not replace it with a macro.

#define PI 3.14
int main()
{
    
    
	printf("%d",PI); //正常打印
	printf("PI"); //写在引号里,将不作宏替换,所以打印出来只是PI两个字母,而不是3.14
	return 0;
}
#undef PI
void func(){
    
    
    printf("%d",PI);//无法识别PI
}

#define with parameters

C language allows macros to take parameters. The parameters in the macro definition are called "formal parameters", and the parameters in the macro call are called "actual parameters".
For example, the following code

#define SQUARE(x)  x * x
int main()
{
    
    
	printf("%d",SQUARE(5));   //结果为25
	printf("%d",SQUARE(5+1)); //结果为11
	return 0;
}

I believe the first 25 is easy to understand, directly 5×5=25, but why is the second one not 6×6=36? The reason is that the
macro is just a simple replacement , so in the second example it is replaced by

printf("%d",5+1 * 5+1); //因为加减乘除的优先级,所以先算1*5,再分别+5再+1

Therefore, macro definitions used to evaluate numerical expressions should be parenthesized in this way to avoid unpredictable interactions between operators in parameters or adjacent operators when using macros.

//改成如下形式
#define SQUARE(x)  (x) * (x)

Note : In a parameterized macro definition, no memory is allocated for the formal parameters , so it is not necessary to specify the data type .

After seeing this, I believe everyone also thinks that functions and macros with parameters are somewhat similar, so I will analyze the difference between the two.
Macros are usually used to perform simple operations.

#define MAX(a, b) ((a)>(b)?(a):(b))  //比较两个数的大小

So why not use functions to accomplish this task?

  1. The code used to call the function and return from the function may take more time than it takes to actually perform this small computational work. Therefore, macros are better than functions in terms of program size and speed.
  2. More importantly, function parameters must be declared as specific types. So functions can only be used on expressions of the appropriate type. On the contrary, how can this macro be applied to integers, long integers, floating point types, etc. It is more flexible in form

Of course, macros also have disadvantages compared to functions:

  1. Each time a macro is used, a copy of the macro definition code is inserted into the program. Unless the macro is relatively short, it may significantly increase the length of the program.
  2. Macros cannot be debugged.
  3. Macros may cause operator precedence problems, making programs prone to errors.

Macros can sometimes do things that functions cannot. For example: macro parameters can have types, but functions cannot

#define MALLOC(num, type)  (type *)malloc(num * sizeof(type))

//在函数中使用时
MALLOC(10, int);//此处int类型就作为了参数之一
//预处理器替换之后:
(int *)malloc(10 * sizeof(int));

The difference between typedef and #define

Finally, we should pay attention to the difference between using macro definitions to represent data types and using typedefs to define data specifiers.

Macro definition is just a simple string replacement, which is processed by the preprocessor in the preprocessing stage; and typedef is processed by the compiler in the compilation stage . It is not a simple string replacement, but gives the original data type a New name, treat it as a new data type.

Guess you like

Origin blog.csdn.net/kklovecode/article/details/132418637