1 Star 0 Fork 0

iint/notes

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
20201028dzh.md
20210505大组会.md
210服务器使用方法.md
4MedianofTwoSortedArray.md
51单片机.md
8大主流服务器程序线程模型.md
ArrayList与LinkedList.md
BNCT.md
C#正则表达式.md
C++的typedef.md
C连接mysql.md
FCN.md
G401.md
History命令用法.md
Interpretbytesaspackedbinarydata.md
IoU.md
K-means聚类算法的理解与案例实战.md
Liner Models.md
Linux下快速比较两个目录的不同.md
MRI-CT工作的数据处理02.md
MRI-CT工作的数据处理03.md
MRI-CT工作的数据处理全过程.md
MRI-CT工作的数据预处理01.md
MRI-CT工作的结果分析01.md
MySQL学习笔记.md
OFDR技术.md
PCA.md
PIL图像处理库简介.md
Paper210309_深度学习预测剂量分布.md
PyTorch常用代码段整理.md
Pythonlambda介绍.md
Pythonxrange()函数.md
Python与C的交互.md
Python中os.sep.join()和os.path.join()的用法和区别.md
Python利用生成器读取大文件数据.md
Python可视化.md
Python将字符串作为变量名.md
Python常用的内建模块.md
Python常用第三方模块.md
Python标准库shutil用法实例详解.md
Python正则表达式.md
Python直接反投影重建CT.md
Python类型注解.md
Python类装饰器.md
Python计算皮尔逊相关系数.md
Python通过钩子远程加载模块.md
Python静态类方法.md
Pytorch中train和eval用法区别.md
Pytorch的BatchNorm层使用中容易出现的问题.md
Pytorch的transforms.md
SQL高质量语句.md
Ubuntu压缩及解压文件.md
__slots__是个什么玩意儿.md
batch_normalization.md
centos7 计划任务 定时运行sh.md
conda.md
cpp list node.md
cpp11并发与多线程.md
cppSTLunordered_map容器用法详解.md
cpphashmap.md
cpp中auto类型用法总结.md
cpp中const的用法.md
cpp中lambda函数.md
cpp中malloc、calloc、realloc函数的用法.md
cpp中set用法详解.md
cpp中using的用法.md
cpp中减去'0'的作用(-'0').md
cpp中的内联函数.md
cpp之namespace常见用法.md
cpp信号处理.md
cpp基础.md
cpp左值引用和右值引用.md
cpp异常处理trycatchthrow.md
cpp提高.md
cpp文件读写.md
cpp核心.md
cpp类中成员变量的初始化.md
cpp预处理器.md
effectivePython.md
github_tutorial.md
https与http.md
k折交叉验证.md
latex.md
leetcode-001.md
leetcode1.TwoSum.md
leetcode11.ContainerWithMostWater.md
leetcode12.IntegertoRoman.md
leetcode131.PalindromePartitioning.md
leetcode15.3Sum.md
leetcode17.LetterCombinationsofaPhoneNumber.md
leetcode22.GenerateParentheses.md
leetcode24.SwapNodesinPairs.md
leetcode3.LongestSubstringWithoutRepeatingCharacters.md
leetcode39.CombinationSum.md
leetcode43.MultiplyStrings.md
leetcode5.LongestPalindromicSubstring.md
leetcode6.ZigZagConversion.md
matplotlib colorbar颜色卡自定义偏移量.md
matplotlib.md
matplotlib_tutorial.md
matplotlib的一些小技巧.md
matplotlib风格.md
mcgpu.md
mysql批量删除重复行.md
namedtuple的使用.md
numpy索引和切片.md
office正则.md
pandas.md
pychram快捷键.md
python-mvisdom.server报[Errno98]Addressalreadyinuse错误解决办法.md
python.md
python_cookbook.md
python关于sorted里面key,reverse以及lamdba,operator这几个鸟人.md
python发送邮件.md
python拟合曲线.md
python正则.md
python爬虫实例-iint入组培训.md
python获取当前目录下的所有文件.md
python装饰器.md
python调用dll动态链接库及ctypes的使用.md
python透明图片和不透明图片叠加合成.md
python闭包.md
python骚操作.md
pytorch分割二分类的两种形式.md
pytorch分布式.md
reids是什么.md
shell.md
shell_cookbook.md
str和repr.md
tqdm.md
vector的六种创建和初始化方法.md
visdom服务启动时提示Downloadingscripts,thismaytakealittlewhile解决...
wordpress迁移.md
yolact.md
中值滤波优化图像结果.md
为什么说relu是激活函数.md
云南旅游计划.md
什么是cpp.md
什么是图神经网络.md
从贝叶斯方法谈到贝叶斯网络.md
优势:杀死乏氧细胞乏氧细胞定义.md
传能线密度.md
使用Python把超大文件当成数组读取.md
共线性.md
利用python快速发送博客到wordpress.md
制作h5py数据集.md
医学图像分割数据集制作.md
医学影像一些概念.md
单例模式.md
南航高性能计算平台介绍.md
卷积的优化.md
原理这就是网络.md
口诀理解Python闭包与装饰器.md
回调函数callback.md
图像分割损失函数设计.md
图像的全变分和去噪.md
基于深度学习的自然图像和医学图像分割:网络结构设计.md
基于蝴蝶网络的双能CT图像域双材料分解.md
多级反馈队列调度算法详解.md
大组会文献汇报.md
安装私有的包.md
将CT值转换为器官组织的one_hot编码.md
工厂模式.md
常见分类算法及他们的优缺点.md
平衡二叉树、B树、B+树、B树.md
应用层.md
快速理解numpy的axis.md
批量删除excel单元格中的换行符.md
损失函数在医学图像分割问题中的应用.md
数值分析作业01.md
数据降维.md
数理逻辑——命题逻辑的基本概念.md
朴素贝叶斯原理及python实现.md
机器学习中,频率派和贝叶斯派有什么核心差异?.md
机器学习十大算法.md
深度学习调参技巧.md
理解主成分分析.md
用Pytorch踩过的坑.md
用python更新主图数据库.md
白化.md
硼中子俘获治疗.md
神经网络不收敛的11个问题.md
神经网络中的注意力机制.md
神经网络工作基本流程.md
群论.md
自动抢羽毛球馆预约.md
英语演讲稿.md
计算机网络.md
计算机网络01-概念、基础.md
设计模式.md
详解AVL树基础篇.md
读写二进制数组数据.md
贝叶斯vs频率派.md
迭代.md
阿里云oss搭建个人图床和网盘.md
雷登变换.md
顺序容器.md
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
C++的typedef.md 6.38 KB
一键复制 编辑 原始数据 按行查看 历史
nuaazs 提交于 4年前 . first

typedef用法详解

用途一

定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。比如: char* pa, pb; 这多数不符合我们的意图,它只声明了一个指向字符变量的指针 和一个字符变量; 以下则可行:

typedef char* PCHAR; // 一般用大写
PCHAR pa, pb; // 可行,同时声明了两个指向字符变量的指针

虽然:char *pa, *pb;也可行,但相对来说没有用typedef的形式直观,尤其在需要大量指针的地方,typedef的方式更省事。

用途二

用在旧的C的代码中(具体多旧没有查),帮助struct。以前的代码中,声明struct新对象时,必须要带上struct,即形式为: struct 结构名 对象名,如:

struct tagPOINT1
{
    int x;
    int y;
};
struct tagPOINT1 p1;

而在C++中,则可以直接写:结构名 对象名,即:

tagPOINT1 p1;

估计某人觉得经常多写一个struct太麻烦了,于是就发明了:

typedef struct tagPOINT  
{  
    int x;  
    int y;  
}POINT;  
POINT p1; // 这样就比原来的方式少写了一个struct,比较省事,尤其在大量使用的时候  

或许,在C++中,typedef的这种用途二不是很大,但是理解了它,对掌握以前的旧代码还是有帮助的,毕竟我们在项目中有可能会遇到较早些年代遗留下来的代码。

用途三

用typedef来定义与平台无关的类型。比如定义一个叫 REAL 的浮点类型,在目标平台一上,让它表示最高精度的类型为: typedef long double REAL; 在不支持 long double 的平台二上,改为: typedef double REAL; 在连 double 都不支持的平台三上,改为: typedef float REAL; 也就是说,当跨平台时,只要改下 typedef 本身就行,不用对其他源码做任何修改。 标准库就广泛使用了这个技巧,比如size_t。另外,因为typedef是定义了一种类型的新别名,不是简单的字符串替换,所以它比宏来得稳健(虽然用宏有时也可以完成以上的用途)。

用途四

为复杂的声明定义一个新的简单的别名。方法是:在原来的声明里逐步用别名替换一部分复杂声明,如此循环,把带变量名的部分留到最后替换,得到的就是原声明的最简化版。举例:

  1. 原声明:int *(*a[5])(int, char*); 变量名为a,直接用一个新别名pFun替换a就可以了: typedef int *(*pFun)(int, char*); 原声明的最简化版:pFun a[5];

  2. 原声明:void (*b[10]) (void (*)()); 变量名为b,先替换右边部分括号里的,pFunParam为别名一:typedef void (*pFunParam)(); 再替换左边的变量b,pFunx为别名二:typedef void (*pFunx)(pFunParam); 原声明的最简化版:pFunx b[10];

  3. 原声明:doube(*)() (*e)[9]; 变量名为e,先替换左边部分,pFuny为别名一:typedef double(*pFuny)(); 再替换右边的变量e,pFunParamy为别名二:typedef pFuny (*pFunParamy)[9]; 原声明的最简化版:pFunParamy e;

理解复杂声明可用的“右左法则”: 从变量名看起,先往右,再往左,碰到一个圆括号就调转阅读的方向;括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直到整个声明分析完。举例: int (*func)(int *p); 首 先找到变量名func,外面有一对圆括号,而且左边是一个*号,这说明func是一个指针;然后跳出这个圆括号,先看右边,又遇到圆括号,这说明 (*func)是一个函数,所以func是一个指向这类函数的指针,即函数指针,这类函数具有int*类型的形参,返回值类型是int

int (*func[5])(int *); func 右边是一个[]运算符,说明func是具有5个元素的数组;func的左边有一个*,说明func的元素是指针(注意这里的*不是修饰func,而是修饰 func[5]的,原因是[]运算符优先级比*高,func先跟[]结合)。跳出这个括号,看右边,又遇到圆括号,说明func数组的元素是函数类型的指 针,它指向的函数具有int*类型的形参,返回值类型为int

也可以记住2个模式: type (*)(....)函数指针 type (*)[]数组指针

陷阱一

记住,typedef是定义了一种类型的新别名,不同于宏,它不是简单的字符串替换。比如: 先定义: typedef char* PSTR; 然后: int mystrcmp(const PSTR, const PSTR);

const PSTR实际上相当于const char*吗?不是的,它实际上相当于char* const。原因在于const给予了整个指针本身以常量性,也就是形成了常量指针char* const。简单来说,记住当const和typedef一起出现时,typedef不会是简单的字符串替换就行。

陷阱二

typedef在语法上是一个存储类的关键字(如auto、extern、mutable、static、register等一样),虽然它并不真正影响对象的存储特性,如: typedef static int INT2; //不可行 编译将失败,会提示“指定了一个以上的存储类”。

typedef 与 #define的区别

案例一

通常讲,typedef要比#define要好,特别是在有指针的场合。请看例子:

typedef char *pStr1;  
#define pStr2 char *;  
pStr1 s1, s2;  
pStr2 s3, s4;  

在上述的变量定义中,s1、s2、s3都被定义为char *,而s4则定义成了char,不是我们所预期的指针变量,根本原因就在于#define只是简单的字符串替换而typedef则是为一个类型起新名字。

案例二

下面的代码中编译器会报一个错误,你知道是哪个语句错了吗?

typedef char * pStr;  
char string[4] = "abc";  
const char *p1 = string;  
const pStr p2 = string;  
p1++;  
p2++;  

p2++出错了。这个问题再一次提醒我们:typedef#define不同,它不是简单的文本替换。上述代码中const pStr p2并不等于const char * p2const pStr p2const long x本质上没有区别,都是对变量进行只读限制,只不过此处变量p2的数据类型是我们自己定义的而不是系统固有类型而已。因此,const pStr p2的含义是:限定数据类型为char *的变量p2为只读,因此p2++错误。

最后记录一下来源

Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/iint/notes.git
git@gitee.com:iint/notes.git
iint
notes
notes
master

搜索帮助