【C语言】_类型重命名typedef关键字

ops/2025/1/12 22:01:41/

目录

1. 从复杂类型理解类型重命名的必要性

1.1 示例1

1.2 示例2

2. typedef 用法

2.1 简单类型重命名

2.2 复杂指针类型重命名

2.2.1 数组指针类型

2.2.2 函数指针类型

3. 使用typedef简化复杂类型的定义

4. #define与typedef


1. 从复杂类型理解类型重命名的必要性

1.1 示例1

( * (void (*) () ) 0 )();

(1)void (*) ( ) 表示函数指针类型;

注:可通过增加变量名识别:void (*p) ( )表示名为p的函数指针变量;

(2) (void (*) () ) 0 实现将0由原本的整型强制类型转换为函数指针类型;

(3)( * (void (*) () ) 0 ) ( ) 表示调用0地址处的无参且返回值为void的函数;

注:0地址不允许用户程序访问,该行代码运行会抛异常;

1.2 示例2

void ( *signal (int, void(*) (int) ) )(int);

(1)void(*) (int) 表示以一个int型为参数且返回值为void的函数指针变量;

(2)signal (int, void(*) (int) ) 表示两个参数分别为int型和函数指针型的,名为signal的函数;

(3)void (* )(int)表示以一个int型为参数且返回值为void的函数指针变量;

注:挖去(2)中已分析部分,得到void ( * )(int);

(4)void ( *signal (int, void(*) (int) ) )(int) 等价于void (* )(int)  signal (int, void(*) (int) ),

(该写法是错误的,但可更直观理解该行代码的功能)

即:声明了一个名为signal的函数,该函数有两个参数,一个为int型,一个为函数指针变量,

并且该函数的返回值也是函数指针类型;

2. typedef 用法

2.1 简单类型重命名

#include<stdio.h>
typedef unsigned int u_int;
typedef int* pint_t;
int main() {// 以下两行等价unsigned int a1;u_int a2;// 以下两行等价int* b1;pint_t b2;return 0;
}

2.2 复杂指针类型重命名

2.2.1 数组指针类型

#include<stdio.h>
typedef int(*pa_t)[5];
int main() {int arr[5] = { 1,2,3,4,5 };int(*pa1)[5] = &arr;pa_t pa2 = &arr;printf("pa1 = %p\n", pa1);printf("pa2 = %p\n", pa2);return 0;
}

运行结果如下: 

注:按照标准格式应写为:typedef int(*)[5] pa_t,但对于数组指针类型,需将重命名后的类型名移至括号内的*边:typedef int(*pa_t)[5];

2.2.2 函数指针类型

#include<stdio.h>
typedef int(*pf_t)(int, int);
int Add(int x, int y) {return x + y;
}
int main() {int(*pf1)(int, int) = &Add;pf_t pf2 = &Add;printf("pf1 = %p\n", pf1);printf("pf2 = %p\n", pf2);return 0;
}

运行结果如下:

注:按照标准格式应写为:typedef int(*)(int, int) pf_t,但对于数组指针类型,需将重命名后的类型移至括号内的*边:typedef int(*pf_t)(int, int);

3. 使用typedef简化复杂类型的定义

(回归示例1与示例2,对应简化)

#include<stdio.h>
typedef void(*pf_t)();
int main() {//	( * (void (*) () ) 0 )();((pf_t)0)();//	void ( *signal (int, void(*) (int) ) )(int);pf_t signal(int, pf_t);return 0;
}

4. #define与typedef

#include<stdio.h>
#include<stdlib.h>
typedef int* pint_t;
#define PINT_T int*
int main() {pint_t p1, p2;// p1 p2都是指针变量PINT_T p3, p4;// p3是指针变量,p4是整型变量return 0;
}

调试借助监视窗口查看变量类型:

理解#define与typedef的区别:

(1)int*一经typedef为pint_t,所有int*会被替换为int*:

	pint_t p1, p2;// 即处理为:// int* p1; int* p2;

(2)#define仅仅实现了符号PINT_T等价为int*:

	PINT_T p3, p4;// 即处理为:// int* p3,p4;// 即:int *p3; int p4;

仅将*分配给p3,即将p3定义为int*型,p4定义为int型;


http://www.ppmy.cn/ops/149564.html

相关文章

阿里云ios镜像源

阿里云镜像源&#xff1a;阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区 下载centos7

排列高手

这篇主要是求再排位为 {1&#xff0c;3&#xff0c;4&#xff0c;....&#xff0c;n&#xff0c;2}的最优顺序下求mex。 但不知道为什么这样是最优 子数列的个数公式&#xff1a; 对于一个长度为N的数组&#xff0c; #include <bits/stdc.h> using namespace std; lon…

企业级信息系统开发讲课笔记4.12 Spring Boot默认缓存管理

文章目录 1. Spring Boot默认缓存管理2. Spring的缓存机制2.1 缓存机制概述2.2 缓存接口和缓存管理接口3. 声明式缓存注解3.1 @EnableCaching注解3.2 @Cacheable注解3.2.1 value/cacheNames属性3.2.2 key属性3.2.3 keyGenerator属性3.2.4 cacheManager/cacheResolver属性3.2.5 …

【C++入门】详解(中)

目录 &#x1f495;1.函数的重载 &#x1f495;2.引用的定义 &#x1f495;3.引用的一些常见问题 &#x1f495;4.引用——权限的放大/缩小/平移 &#x1f495;5. 不存在的空引用 &#x1f495;6.引用作为函数参数的速度之快&#xff08;代码体现&#xff09; &#x1f4…

计算机基础知识复习1.5

标记-清除算法&#xff1a;标记-清除分为标记 和清除 两个阶段&#xff0c;首先通过可达性分析&#xff0c;标记出所有需要回收的对象&#xff0c;然后统一回收所有被标记的对象。 复制算法&#xff1a;为了解决碎片空间的问题&#xff0c;出现了复制算法 将内存分成两块&…

2501wtl,皮肤技术

下载地址 设计目标 最重要的是使用方便,已有程序创建一个COM对象,调一个方法就可把界面外观全部改成Mac风格的. 另外一个目标是要有扩展性. 所以,基本设计是定义一个统一的接口,然后用不同实现.每一个实现单独放在一个COMDLL中,调用者选择一个类标创建对象就行了. 接口的定义…

鸿蒙中自定义slider实现字体大小变化

ui&#xff1a; import { display, mediaquery, router } from kit.ArkUI import CommonConstants from ./CommonConstants; import PreferencesUtil from ./PreferencesUtil; import StyleConstants from ./StyleConstants;// 字体大小 Entry Component struct FontSize {Sta…

c语言提供后端,提供页面显示跳转服务

后端代码: #define SERVER_IP_ADDR "0.0.0.0" // 服务器IP地址 #define SERVER_PORT 8080 // 服务器端口号 #define BACKLOG 10 #define BUF_SIZE 8192 #define OK 1 #define ERROR 0#include <stdio.h> #include <stdlib.h> #include <st…