typedef用法和陷阱
一、typedef的用法
1.用typedef来声明新的类型名,来代替已有的类型名,也就是给类型起别名。比如
typedef float REAL; //用REAL来代表float类型
REAL a; //定义一个REAL类型的变量,等价于float a,即定义一个float类型的变量a
这种用法经常用来作为定义与平台无关的类型,方便代码的跨平台移植。
例如,定义REAL类型为目标平台精度最高的类型。
1>在支持long double的平台上定义为:
typedef long double REAL;
注:long double为C99增加的类型,ANSI C标准规定了double变量存储为 IEEE 64 位(8 个字节)浮点数值,但并未规定long double的确切精度,但规定long double的精度不少于double的精度。所以对于不同平台long double可能有不同的实现,有的是8字节,有的是10字节,有的是12字节或16字节。关于具体的编译器的情况, 可以通过 sizeof(long double)得知。
2>在不支持long double的平台上改为
typedef double REAL;
3>在double不支持的平台上改为
typedef float REAL;
因此,当跨平台时,只要改下 typedef 本身就行,不用对其他源码做任何修改。
2.为自定义数据结构(如struct、union)定义简洁易记的类型名。
比如:
struct data{
int month;
int day;
int year;
}; //定义一个data的结构体
声明结构体变量时,代码如下
struct data birthday;
用typedef可以定义新的类型,代替上面的结构体类型
typedef struct data{
int month;
int day;
int year;
}DATA; //定义一个data的结构体
DATA birthday; //定义一个DATA类型的变量birthday,等价于上面struct data类型
注:这种方法在一些代码规范中是不推荐和禁止的,因为新的类型隐藏了具体的类型,不利于看代码的人直观了解到实际类型。
3.用typedef来声明新的类型
1>可以用来简化数组变量定义
typedef int ARR[]; //定义类型ARR为含有10个元素的int数组
ARR arr_a, arr_b; //定义了两个含有10个元素的int数组变量arr_a,arr_b
2>简化指针变量的定义
typedef int* INT_P
INT_P p1,p2; //定义两个int指针变量p1、p2
注意,下面的定义容易引起错误,所以编程规范中禁止一次声明多个变量
int* p1, p2; //p1为int*类型,p2为int类型
typedef char* STRING;
STRINT p; //p为字符串指针变量
STRINT s[]; //s为指针数组,即s为一个含有10个元素的数组,每个元素是一个字符串指针 typedef int (* POINTER)(); //声明POINTTER为指向函数的指针类型,该函数返回值为int类型
POINTER p1,p2; //p1,p2均为函数指针变量;
4.为复杂的声明定义一个新的简单的别名。
int *(*a[])(int, char*); //变量名为a,直接用一个新别名pFun替换a typedef int *(*pFun)(int, char*);
pFun a[]; //定义一个含有5个函数指针的数组
void (*b[]) (void (*)()); //原声明,b为含有10个元素的函数指针数组,其参数为不带参数的函数指针 typedef void (*pFunParam)();//声明不带参数的函数指针为类型pFunParam
typedef void (*pFunx)(pFunParam); //声明pFunx为函数指针
pFunx b[]; //函数指针数组b
doube(*)() (*e)[]; //变量e为指针,该指针指向一个数组,该数组含有9个元素,每个元素为一个函数指针,该函数指针的返回值为double类型
简化写法:
typedef double(*pFuny)(); //声明一个函数指针别名pFuny,返回类型为double
typedef pFuny (*pFunParamy)[]; //声明一个指针
pFunParamy e;//声明变量e为pFunParamy类型
理解复杂声明可用的“右左法则”:
从变量名看起,先往右,再往左,碰到一个圆括号就调转阅读的方向;括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直到整个声明分析完。举例:
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的陷阱
1.typedef是一种新类型的声明,不是简单的字符串替换,不同于#define
例如:
typedef char* STRING;
int strcmp(const STRING,const STRING);
在上面的代码中,“const STRING” 是否相当于 “const char*” 呢?
答案是否定的,原因很简单,typedef 是用来声明一种新的类型,它不同于宏,不是简单的字符串替换。STRING已经是一种类型,const修改该类型为常量。因此,“const STRING”中的 const 给予了STRING常量属性,也就是整个指针本身常量性,也即形成了常量指针“char*const(一个指向char的常量指针)”。
即它实际上相当于“char*const”,而不是“const char*(指向常量 char 的指针)”。当然,要想让 const PCHAR 相当于 const char* 也很容易,如下面的代码所示:
typedef const char* PCHAR;
int strcmp(PCHAR, PCHAR);
因此,无论什么时候,只要为指针声明 typedef,那么就应该在最终的 typedef 名称中加一个 const,以使得该指针本身是常量。
2.typedef 和存储类关键字(storage class specifier)
typedef在语法上是一个存储类的关键字(如auto、extern、mutable、static、register等一样),虽然它并不真正影响对象的存储特性。
例如下面的代码会编译报错:
typedef static int INT_STATIC;
参考:
https://www.cnblogs.com/a-s-m/p/10995722.html
http://c.biancheng.net/view/298.html
typedef用法和陷阱的更多相关文章
- typedef用法和与define的区别
typedef用来声明一个别名,typedef后面的语法,是一个声明.本来笔者以为这里不会产生什么误解的,但结果却出乎意料,产生误解的人不在少数.罪魁祸首又是那些害人的教材.在这些教材中介绍typed ...
- typedef 深入剖析
typedef是一个我们常常会用到的关键字,而这个关键字有许多陷阱或者说许多不为我们深入理解的地方.很多书上都是很简单地一笔代过,并没有真正地让我们理解这个关键字.本文对其进行详细地说明.综合网络上找 ...
- struct 和typedef struct
1.typedef (1)typedef的使用 定义一种类型的别名,而不只是简单的宏替换(见陷阱一).用作同时声明指针型的多个对象 typedef char* PCHAR; // 一般用大写,为cha ...
- typedef define typedef可以使程序参数化,提高程序的可移植性。
小结: 1. typedef并没有创建一个新类型,它只是为某个已存在的类型增加了一个新的名称而已: 2. typedef声明也没有证据新的语义:通过这种方式声明的变量与通过普通方式声明的变量具有完全相 ...
- C语言typedef详解
原文链接 C语言允许用户使用 typedef 关键字来定义自己习惯的数据类型名称,来替代系统默认的基本类型名称.数组类型名称.指针类型名称与用户自定义的结构型名称.共用型名称.枚举型名称等.一旦用户在 ...
- C++有关 const & 内敛 & 友元&静态成员那些事
C++中有关 const & 内敛 & 友元&静态成员 的用法比较杂乱,算是C++中一个麻烦的部分.现速速的对它们做大致的总结,了解它们当中常见的用法和陷阱. const修饰的 ...
- 改善c++程序的150个建议(读后总结)-------12-18
12.优先使用前置操作符 #include <iostream> using namespace std; class A { private: int num; public: A op ...
- 揭秘 typedef四用途与两陷阱[转]
自 http://niehan.blog.techweb.com.cn/archives/325.html typedef用来声明一个别名,typedef后面的语法,是一个声明.本来笔者以为这里不会产 ...
- struct和typedef struct用法和区别
1 首先://注意在C和C++里不同 1.1 在C中定义一个结构体类型要用typedef: typedef struct Student { int a; }Stu; 于是在声明变量的时候就可:Stu ...
随机推荐
- 独立成分分析 ICA 原理及公式推导 示例
独立成分分析(Independent component analysis) 前言 独立成分分析ICA是一个在多领域被应用的基础算法.ICA是一个不定问题,没有确定解,所以存在各种不同先验假定下的求解 ...
- 【CSP模拟赛】方程(数学)
题目描述 求关于x的方程:x1+x2+……xk=n的非负整数解的个数. 输入格式 仅一行,包含两个正整数n,k. 输出格式 一个整数,表示方程不同解的个数,这个数可能很大,你只需输出mod 20080 ...
- 消息队列Rabbit MQ 学习第一篇
1 介绍 1.1RabbitMQ MQ全称为Message Queue,即消息队列, RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队 ...
- ubuntu之路——day10.1 ML的整体策略——正交化
orthogonalization 正交化的概念就是指,将你可以调整的参数设置在不同的正交的维度上,调整其中一个参数,不会或几乎不会影响其他维度上的参数变化,这样在机器学习项目中,可以让你更容易更快速 ...
- Assignment4:闰年判断输入异常时的处理方法
一.问题描述 在输入界面输入年份,界面返回是否为闰年. 判断依据为:输入的数字可以被4整除但不可以被100整除 || 输入的数字可以被400整除 如果输入为数字以外的其他字符,会抛出异常.那么如何防止 ...
- 帮谷歌推广Webp图片格式之:Webp的格式转换
参考谷歌官网:Webp: A new image format for the Web Webp是Google强推的新一代网络图片格式,特点就是:高质量压缩.能压缩多少呢?5MB的原图,不降低效果,转 ...
- NPAPI绘图和事件处理
https://developer.mozilla.org/en-US/docs/Plugins/Guide/Drawing_and_Event_Handling 本章介绍如何确定插件实例是窗口化还是 ...
- Java TreeSet,Collections使用
一.创建TreeSet实例 public static void main(String[] args) { TreeSet set = new TreeSet(); set.add("C& ...
- python 与开源Gis 书本知识点测试
# -*- coding: utf-8 -*- print(u"python与开源QGis课题研究组")#print("汉字") #++++++++++++++ ...
- 微信小程序的z-index在苹果ios无效
1.在微信开发者工具可以正常显示 2.在安卓真机手机可以正常显示 3.在ios手机真机无法正常显示 原因:父级view的css属性有 position: fixed; ,把它注释掉即可