请讲解下typedef的使用

fallening 2008-04-28 03:15:52
这里找到了一个不错的讲解,但是给出的例子代码是错误的;因此,不知道它所说的哪些是正确的,请高手讲解下。
如这段示例代码
#include <iostream>
#include <string>
using namespace std;

typedef struct Student;
typede#include <iostream>
#include <string>
using namespace std;

typedef struct Student;
typedef class Country;

typedef public short SmallNumber;
typedef private unsigned int Positive;
typedef protected double* PDouble;
typedef public string FiveStrings[5];
typedef private double (*Addition)(double value1, double value2);

struct Student
{
string FirstName;
string LastName;
};

f class Country;

typedef public short SmallNumber;
typedef private unsigned int Positive;
typedef protected double* PDouble;
typedef public string FiveStrings[5];
typedef private double (*Addition)(double value1, double value2);

struct Student
{
string FirstName;
string LastName;
};
typedef struct _Empl
{
string FullName;
double HourlySalary;
}Employee;

class Country
{
string Name;
string Capital;
string Code;
};

double Add(double x, double y)
{
double result = x + y;
return result;
}

typedef enum EmplStatus { esFullTime, esPartTime, esContractor };
typedef Student *PStudent;
typedef Country *PCountry;

int main()
{
Student pupil;
Country pais;
EmplStatus emplst;
PStudent ptrStd = new Student;
PCountry pPais = new Country;

return 0;
}typedef struct _Empl
{
string FullName;
double HourlySalary;
}Employee;

class Country
{
string Name;
string Capital;
string Code;
};

double Add(double x, double y)
{
double result = x + y;
return result;
}

typedef enum EmplStatus { esFullTime, esPartTime, esContractor };
typedef Student *PStudent;
typedef Country *PCountry;

int main()
{
Student pupil;
Country pais;
EmplStatus emplst;
PStudent ptrStd = new Student;
PCountry pPais = new Country;

return 0;
}

编译错误如下(内存泄漏暂且不管了)

ss.cc:5: warning: ‘typedef’ was ignored in this declaration
ss.cc:6: warning: ‘typedef’ was ignored in this declaration
ss.cc:8: error: expected unqualified-id before ‘public’
ss.cc:9: error: expected unqualified-id before ‘private’
ss.cc:10: error: expected unqualified-id before ‘protected’
ss.cc:11: error: expected unqualified-id before ‘public’
ss.cc:12: error: expected unqualified-id before ‘private’
ss.cc:39: warning: ‘typedef’ was ignored in this declaration
ss.cc: In function ‘int main()’:
ss.cc:47: warning: unused variable ‘emplst’
ss.cc:48: warning: unused variable ‘ptrStd’
ss.cc:49: warning: unused variable ‘pPais’


下一楼给出全文

...全文
777 32 打赏 收藏 转发到动态 举报
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
qmm161 2008-05-06
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 MagiSu 的回复:]
坚决鄙视thq,要看就看expertc programming,里面解释得很清楚!
抄一段以前的笔记。[/Quote]

不知道你有认真看过谭老师那本书没有?关于typedef这段的描述是很简单而且到位的!不要动不动就坚决鄙视!
fallening 2008-04-30
  • 打赏
  • 举报
回复
木有接分的了么?
我要结贴了哦
con_con 2008-04-30
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 fallening 的回复:]
18楼到22楼的发言都没有提及这两个用法

1. The typedef keyword can be followed by an attribute before the data type.
In its simplest form, the attribute can be that of an access level
such as public, private, or protected.
所以,下边这段代码是错误的


C/C++ codetypedef public short SmallNumber;
typedef private unsigned int Positive;
typedef protected double* PDouble;
typedef pub…
[/Quote]

这样的就狠正确
Learn-anything 2008-04-30
  • 打赏
  • 举报
回复
接……
Walker-cheng 2008-04-29
  • 打赏
  • 举报
回复
不错,
Inhibitory 2008-04-29
  • 打赏
  • 举报
回复
CSDN上回答问题的多寡, 基本上由分决定
MagiSu 2008-04-29
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 qmm161 的回复:]
typedef struct Student;
typedef class Country;

typedef public short SmallNumber;
typedef private unsigned int Positive;
typedef protected double* PDouble;
typedef public string FiveStrings[5];
typedef private double (*Addition)(double value1, double value2);

没一个是对的!没见过typedef里面用public private protected的!
前面两个更是离谱!

看 typedef 的用法就看谭浩强老师绿壳…
[/Quote]
坚决鄙视thq,要看就看expertc programming,里面解释得很清楚!
抄一段以前的笔记。

typedef Can be your friend
对于形如void (*signal(int,void (*) (int)) (int),容易推导出含义为:a pointer to a function takes int and function void (*) (int) as parameter and return a pointer to a function takes int and return void.
采用typedef void (*fun_argument) (int); 可以简化为fun_argument signal(int,fun_argument);
typedef一行只要定义一个类型,并且typedef应该放在最前面。

Difference between typedef and #define
例如:typedef int* intp_tag; #define int* intp_def;
intp_def a,b; // a is int* while b is int
intp_tag a,b; // both a and b are int*

typdef struct foo { ... foo; } foo;
第一个foo是struct用到的,称作tag,第二个foo是成员变量名,第三个是类型名。
第一个foo使用的时候必须前面加上struct标明是struct。
第三个foo则不需要加上struct,因为它是类型名。

typdef应当用于以下三种用处,而不应用于struct的缩写:
1、组合function,array,structs
2、可能用到的跨平台类型。
3、类型转换。
systemthink 2008-04-29
  • 打赏
  • 举报
回复
MARK.
fallening 2008-04-29
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 dizuo 的回复:]
C/C++ code你什么编译器啊,
你的代码,我试了一下,就是几个warning啊,没有error,
[/Quote]
$ g++ -v
Using built-in specs.
Target: i686-pc-linux-gnu
Configured with: ../configure --prefix=/usr --enable-shared --enable-languages=c,c++,fortran,objc,obj-c++,treelang --enable-threads=posix --mandir=/usr/share/man --enable-__cxa_atexit --disable-multilib --libdir=/usr/lib --libexecdir=/usr/lib --enable-clocale=gnu --disable-libstdcxx-pch --with-tune=generic
Thread model: posix
gcc version 4.3.0 (GCC)
$ uname -a
Linux enlightenment 2.6.25-ARCH #1 SMP PREEMPT Sat Apr 19 15:39:26 CEST 2008 i686 Intel(R) Pentium(R) M processor 1.60GHz GenuineIntel GNU/Linux
fallening 2008-04-29
  • 打赏
  • 举报
回复
18楼到22楼的发言都没有提及这两个用法

1. The typedef keyword can be followed by an attribute before the data type.
In its simplest form, the attribute can be that of an access level
such as public, private, or protected.

所以,下边这段代码是错误的

typedef public short SmallNumber;
typedef private unsigned int Positive;
typedef protected double* PDouble;
typedef public string FiveStrings[5];
typedef private double (*Addition)(double value1, double value2);



2. In C++, the attribute of the typedef is usually applied as
a class, a struct, or an enum.

所以,下边这段也是不对的

typedef struct Student;
typedef class Country;

但是
typedef struct _Empl
{
string FullName;
double HourlySalary;
}Employee;

正确

abupie 2008-04-29
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 fallening 的回复:]
这样说来,下边这两个论断似乎完全错误的了,对么?
In C++, the typedef keyword allows you to create an alias for a data type. The formula to follow is:

C/C++ codetypedef [attributes] DataType AliasName;


The typedef keyword can be followed by an attribute before the data type. In its simplest form, the attribute can be that of an access level such as public, private, or protected. 错误

[/Quote]
??哪里错了?
fallening 2008-04-29
  • 打赏
  • 举报
回复
这样说来,下边这两个论断似乎完全错误的了,对么?
In C++, the typedef keyword allows you to create an alias for a data type. The formula to follow is:
typedef [attributes] DataType AliasName;

The typedef keyword can be followed by an attribute before the data type. In its simplest form, the attribute can be that of an access level such as public, private, or protected. 错误
In C++, the attribute of the typedef is usually applied as a class, a struct, or an enum.
错误
Irene12 2008-04-29
  • 打赏
  • 举报
回复
用途一:
定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。比如:
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; //不可行
编译将失败,会提示“指定了一个以上的存储类”。
Irene12 2008-04-29
  • 打赏
  • 举报
回复
typedef到处都是,但是能够真正懂得typedef使用的不算太多。对于初学者而言,看别人的源码时对到处充斥的typedef往往不知所错,而参考书又很少,所以在此给出一个源码,供大家参考



#include <stdio.h>

#include <iostream.h>




/* 避免Visual C的for与标准for的不同 */

#define for if (0); else for



/* dim(a)是用于计算a的维数,不过只能计算数组的维数,不能计算指针的维数 */

#define dim(a) (sizeof(a)/sizeof(a[0]))



/* N1到N4是几个常量,以枚举的形式定义 */

enum {N1 = 2, N2 = 3, N3 = 4, N4 = 5};



/* 这个C程序员都知道,就是将DataType定义为int型,便于扩充 */

typedef int DataType;



/* 定义一个一维数组,数组的元素维整型值 */

typedef DataType ARR1[N4];



/* 再定义一个一维数组,数组的元素维ARR1型,不过ARR1又是一个数组,所以

* ARR2 实际上是一个矩阵

*/

typedef ARR1 ARR2[N3]; /* 此处完全等价为typedef int ARR2[N3][N4];*/



/* 按照ARR2的解释,ARR3也是一个一维数组,不过数组元素的类型是ARR2的类型

* 所有ARR3是一个三维数组

*/

typedef ARR2 ARR3[N2]; /* 此处完全等价为typedef int ARR3[N2][N3][N4];*/



/* 分别用定义好的ARR1,ARR2,ARR3定义三个变量a, b, c */

ARR1 a; /* 此处完全等价于:int a[N4]; */

ARR2 b; /* 此处完全等价于:int b[N3][N4]; */

ARR3 c; /* 此处完全等价于:int c[N2][N3][N4]; */



/* 下面函数给大家个示例看a,b,c如何使用 */

void exam_1()

{

for (int i=0; i<dim(a); i++) a[i] = i+1;



for (int i=0; i<dim(b); i++) for (int j=0; j<dim(b[0]); j++)

b[i][j] = (i+1)*10 + (j+1);



for (int i=0; i<dim(c); i++) for (int j=0; j<dim(c[0]); j++)

for (int k=0; k<dim(c[0][0]); k++) c[i][j][k] = (i+1)*100 + (j+1)*10 + (k+1);



printf("\nThe a is :\n");

for (int i=0; i<dim(a); i++) printf("%4d ", a[i]);

printf("\n");



printf("\nThe b is :\n");

for (int i=0; i<dim(b); i++)

{

for (int j=0; j<dim(b[0]); j++) printf("%4d ", b[i][j]);

printf("\n");

}



printf("\nthe c is:\n");

for (int i=0; i<dim(c); i++)

{

for (int j=0; j<dim(c[0]); j++)

{

for (int k=0; k<dim(c[0][0]); k++) printf("%4d ", c[i][j][k]);

printf("\n");

}

printf("\n");

}

}



/* 下面函数给大家演示数组在内存中的排列 */

void exam_2()

{

int *pn = NULL;



pn = (int *)a; /* 等价于 pn = &a[0]; */

printf("\nThe a is :\n");

for (int i=0; i<sizeof(a)/sizeof(DataType); i++) printf("%4d ", pn[i]);

printf("\n");



pn = (int *)b; /* 等价于 pn = &b[0][0]; */

printf("\nThe b is :\n");

for (int i=0; i<sizeof(b)/sizeof(DataType); i++) printf("%4d ", pn[i]);

printf("\n");



pn = (int *)c; /* 等价于 pn = &c[0][0][0]; */

printf("\nThe c is :\n");

for (int i=0; i<sizeof(c)/sizeof(DataType); i++) printf("%4d ", pn[i]);

printf("\n");

}







int main(int argc, char* argv[])

{

exam_1();

exam_2();

return 0;

}

独孤过儿 2008-04-29
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 dizuo 的回复:]
C/C++ code你什么编译器啊,
你的代码,我试了一下,就是几个warning啊,没有error,
[/Quote]
dizuo兄也要check一下你的编译器是否需要更新了,呵呵...
ryfdizuo 2008-04-29
  • 打赏
  • 举报
回复
你什么编译器啊,
你的代码,我试了一下,就是几个warning啊,没有error,
独孤过儿 2008-04-29
  • 打赏
  • 举报
回复

用途一:

定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。比如:

char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针,

// 和一个字符变量;

以下则可行:

typedef char* PCHAR;

PCHAR pa, pb;



用途二:

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

struct tagPOINT1

{

int x;

int y;

};

struct tagPOINT1 p1;



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

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是定义了一种类型的新别名,不是简单的字符串替换,所以它比宏来得稳健。



用途四:

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

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

hai040 2008-04-29
  • 打赏
  • 举报
回复
lz的程序去掉
typedef struct Student;
typedef class Country;
就可以编译
fallening 2008-04-29
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 Treazy 的回复:]
个人建议你看下

c缺陷与陷阱

里面讲的很清楚了……
[/Quote]
刚才去打印出来翻了一下,好像只有20页短短的几句:
This defines FOOTYPE as a new type that is equivalent to struct foo. These two ways of naming a type may appear to be equivalent, but the typedef is more flexible. Consider, for example, the following:
#define T1 struct foo *
typedef struct foo *T2;

These definitions make T1 and T2 conceptually equivalent to a pointer to a struct foo. But look what happens when we try to use them with more than one variable:
T1 a, b;
T2 c, d;

The first declaration gets expanded to
struct foo * a, b;

This defines a to be a pointer to a structure, but defines b to be a structure (not a pointer). The second declaration, in contrast, defines both c and d as pointers to structures, because T2 behaves as a true type.

文件是从贝尔实验室那边下的http://cm.bell-labs.com/cm/cs/cstr/123.ps.gz
Treazy 2008-04-29
  • 打赏
  • 举报
回复
个人建议你看下

c缺陷与陷阱

里面讲的很清楚了……
加载更多回复(12)

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧