typedef 含义与用法总结 汇总+修改

来源:互联网 发布:python item 编辑:程序博客网 时间:2024/06/05 10:21

第一个用途:定义一种类型的别名,不仅仅是简单宏的定义,可以同时声明指针型的多个对象。比如、

char * pa , pb;     //声明一个指向字符变量的指针和一个字符变量

typedef char* PCHAR;

PCHAR pa,pb;     //声明两个指向char类型的指针;


第二个用途:在旧的c代码中,声明新的结构对象,需要关键字struct

格式为:struct + 结构名+对象名

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

在c++中则可以直接写为:结构名+对象名  tagPOINT1 p1;

typedef struct tagPOINT
{
    int x;
    int y;
}POINT;

POINT p1;POINT 作为tagPOINT的类型别名。


用途三 用来定义和平台无关的类型

比如定义一个REAL浮点类型,在目标平台上表示最高精度类型为:

typedef  long double REAL;

在不支持long double的平台上改为:

typedef   double REAL;

在不支持double的平台上,改为

typedef  float REAL;

跨平台操作的实现只需要修改typedef本身,不用对源码进行修改。

typedef定义一种类型的新别名,不是简简单单的字符串替换,

用途四:用复杂的声明定义一个新的简单别名,在声明中逐步用别名替换一部分复杂声明,如此循环,把带变量名的部分留到最后替换,得到的就是原声明的最简化版本。

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


 原声明: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。

#include <iostream>
using namespace std;
typedef int (*A) (char, char);
int ss(char a, char b)
{
    cout<<"功能1"<<endl;
    cout<<a<<endl;
    cout<<b<<endl;
    return 0;
}
int bb(char a, char b)
{
    cout<<"功能2"<<endl;
    cout<<b<<endl;
    cout<<a<<endl;
    return 0;
}
void main()
{    A a;
a = ss;
a('a','b');
    a = bb;
    a('a', 'b');
}


/*typedef int (A) (char, char);
void main()
{    A *a;
    a = ss;
    a('a','b');
    a = bb;
    a('a','b');
}*/


如同typedef和define的区别:

案例一:
通常讲,typedef要比#define要好,特别是在有指针的场合。请看例子:
typedef char *pStr1;
#define pStr2 char *;
pStr1 s1, s2;
pStr2 s3, s4;
在上述的变量定义中,s1、s2、s3都被定义为char *,而s4则定义成了char,不是我们
所预期的指针变量,根本原因就在于#define只是简单的字符串替换而typedef则是为一
个类型起新名字。


案例二:

#include <iostream>
using namespace std;
typedef  char * pStr;
void main()
{  
char string[4] = "abc";
const char *p1 = string;
const pStr p2 = string;
p1++;
p2++;
}

案例中pstr指的就是一个指向char类型的指针类型,可以暂时理解为int。

const pstr p2=string;相当于const int  p2=3;所以运行出错

这就限制了p2是一个不可修改的int常量,永远就是3,只能使用不能修改。

const char *p1 = string;

const char *p1 = string 意思是说一个指向const char类型的指针。

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

p2[2] = 'e';

printf(p2);p2可以对string数组中的值进行改变。

#include<stdio.h>

int main(){
typedef char * pStr;
char string[4] = "abc";
const char *p1 = string;
const pStr p2 = string;
p1[1] = 'f';不能给常量赋值
p1++;
p2[2] = 'e';// 可以赋值
p2++;//指针不可移动
printf(p1);
printf(p2);
return 0;
}
下面是错误:
1>c:\test\typedef.cpp(8): error C3892: “p1”: 不能给常量赋值
1>c:\test\typedef.cpp(11): error C3892: “p2”: 不能给常量赋值

当const char * p1时,const修饰的是char,所以p1不能修改指向的值;
当const PStr p2时,const修饰的是p2,所以p2不能对自身做任何修改;


以下为对精彩评论的引用:

其实,在这里主要就是对const的作用范围的理解。
typedef char * pStr;
char string1[4] = "abc";
char string2[4] = "def";
const char *p1 = string1;
const pStr p2 = string1;

p1[1] = 'f'; // 此句错
p1++; // 此句对
p1 = string2; // 此句对
p1[1] = 'x'; // 此句错

p2[1] = 'f'; // 此句对
p2++; // 此句错
p2 = string2; // 此句错

在const char *p1中,const的作用力量在p1所指的内容,也就是说,当p1指向string1时,string1的内容相对于p1来说是常量,是固定的,是不能改变的,所以p1[1] = 'f'这一句就是错误的,而p1自身的值(即地址值)是可以改变的,所以p1++和p1 = string2都是正确的。
在const pStr p2中,const的作用力量在p2,即p2是个常量,p2的值实际上是个地址,也就是说,p2已经固定了,它的值是不能变的,但它这个地址所指的内容是可以改变的,所以p2[1] = 'f'是对的,但p2 = string2是错误的,因为这句是想将另一个地址赋值给p2。
总体来说,一个是将内容固定为常量,一个是将地址固定为常量,也就是指针常量和常量指针的说法,p1是常量指针,p2是指针常量。这也是C中指针的魅力所在。








0 0
原创粉丝点击