typedef define typedef可以使程序参数化,提高程序的可移植性。
extern "C"
小结:
1、
typedef并没有创建一个新类型,它只是为某个已存在的类型增加了一个新的名称而已;
2、
typedef声明也没有证据新的语义:通过这种方式声明的变量与通过普通方式声明的变量具有完全相同的属性;
3、
类似于#define,但typedef是由编译器解释的,因此它的文本替换供功能要超过预处理器的功能;
4、
typedef可以使程序参数化,提高程序的可移植性。如果typedef声明的数据类型同机器有关,那么,当程序移植到其他机器上时,只需该表typedef类型定义就可以了。
一个经常用到的情况是,对于各种不同大小的整型值来说,都使用通过typedef定义的类型名,然后,分别为各个不同放入宿主机选择一组合适的short、int和logn类型大小即可。
标准库中有一些例子,例如size_t和ptrdiff_t等。
5、
C语言支持在结构中包含一个指向它自己的指针。
6、
“使用typedef关键字定义结构体类型,同时给出别名” 与 “义结构体类型的同时定义结构体类型变量”
别名可以仍用原名
6.7 Typedef
C provides a facility called typedef for creating new data type names. For example, the declaration
typedef int Length;
makes the name Length a synonym for int. The type Length can be used in declarations, casts, etc., in
exactly the same ways that the int type can be:
Length len, maxlen;
Length *lengths[];
Similarly, the declaration
typedef char *String;
makes String a synonym for char * or character pointer, which may then be used in declarations and
casts:
String p, lineptr[MAXLINES], alloc(int);
int strcmp(String, String);
p = (String) malloc(100);
Notice that the type being declared in a typedef appears in the position of a variable name, not right after
the word typedef. Syntactically, typedef is like the storage classes extern, static, etc. We have
used capitalized names for typedefs, to make them stand out.
The C programming Language
6.7 Typedef 133
As a more complicated example, we could make typedefs for the tree nodes shown earlier in this chapter:
typedef struct tnode *Treeptr;
typedef struct tnode { /* the tree node: */
char *word; /* points to the text */
int count; /* number of occurrences */
struct tnode *left; /* left child */
struct tnode *right; /* right child */
} Treenode;
This creates two new type keywords called Treenode (a structure) and Treeptr (a pointer to the
structure). Then the routine talloc could become
Treeptr talloc(void)
{
return (Treeptr) malloc(sizeof(Treenode));
}
It must be emphasized that a typedef declaration does not create a new type in any sense; it merely adds a
new name for some existing type. Nor are there any new semantics: variables declared this way have exactly
the same properties as variables whose declarations are spelled out explicitly. In effect, typedef is like
#define, except that since it is interpreted by the compiler, it can cope with textual substitutions that are
beyond the capabilities of the preprocessor. For example,
typedef int (*PFI)(char *, char *);
creates the type PFI, for ``pointer to function (of two char * arguments) returning int,'' which can be used
in contexts like
PFI strcmp, numcmp;
in the sort program of Chapter 5.
Besides purely aesthetic issues, there are two main reasons for using typedefs. The first is to parameterize a
program against portability problems. If typedefs are used for data types that may be machine−dependent,
only the typedefs need change when the program is moved. One common situation is to use typedef
names for various integer quantities, then make an appropriate set of choices of short, int, and long for
each host machine. Types like size_t and ptrdiff_t from the standard library are examples.
The second purpose of typedefs is to provide better documentation for a program − a type called Treeptr
may be easier to understand than one declared only as a pointer to a complicated structure.
FROM
The C programming Language By Brian W. Kernighan and Dennis M. Ritchie.
https://docs.microsoft.com/zh-cn/cpp/c-language/null-statement-c?view=vs-2017
typedef的用法,C语言typedef详解 http://c.biancheng.net/view/298.html
http://www.runoob.com/cprogramming/c-typedef.html
https://www.tutorialspoint.com/cprogramming/c_typedef.htm
The C programming language provides a keyword called typedef, which you can use to give a type a new name.
typedef vs #define
#define 是 C 指令,用于为各种数据类型定义别名,与 typedef 类似,但是它们有以下几点不同:
- typedef 仅限于为类型定义符号名称,#define 不仅可以为类型定义别名,也能为数值定义别名,比如您可以定义 1 为 ONE。
- typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的。
typedef vs #define
#define is a C-directive which is also used to define the aliases for various data types similar to typedef but with the following differences −
-
typedef is limited to giving symbolic names to types only where as #define can be used to define alias for values as well, q., you can define 1 as ONE etc.
-
typedef interpretation is performed by the compiler whereas #define statements are processed by the pre-processor.
typedef的4种用法
在实际使用中,typedef 的应用主要有如下4种。
1) 为基本数据类型定义新的类型名
也就是说,系统默认的所有基本类型都可以利用 typedef 关键字来重新定义类型名,示例代码如下所示:
- typedef unsigned int COUNT;
而且,我们还可以使用这种方法来定义与平台无关的类型。比如,要定义一个叫 REAL 的浮点类型,在目标平台一上,让它表示最高精度的类型,即:
- typedef long double REAL;
在不支持 long double 的平台二上,改为:
- typedef double REAL;
甚至还可以在连 double 都不支持的平台三上,改为:
- typedef float REAL;
这样,当跨平台移植程序时,我们只需要修改一下 typedef 的定义即可,而不用对其他源代码做任何修改。其实,标准库中广泛地使用了这个技巧,比如 size_t 在 VC++2010 的 crtdefs.h 文件中的定义如下所示:
- #ifndef _SIZE_T_DEFINED
- #ifdef _WIN64
- typedef unsigned __int64 size_t;
- #else
- typedef _W64 unsigned int size_t;
- #endif
- #define _SIZE_T_DEFINED
- #endif
2) 为自定义数据类型(结构体、共用体和枚举类型)定义简洁的类型名称
以结构体为例,下面我们定义一个名为 Point 的结构体:
- struct Point
- {
- double x;
- double y;
- double z;
- };
在调用这个结构体时,我们必须像下面的代码这样来调用这个结构体:
- struct Point oPoint1={100,100,0};
- struct Point oPoint2;
在这里,结构体 struct Point 为新的数据类型,在定义变量的时候均要向上面的调用方法一样有保留字 struct,而不能像 int 和 double 那样直接使用 Point 来定义变量。现在,我们利用 typedef 定义这个结构体,如下面的代码所示:
- typedef struct tagPoint
- {
- double x;
- double y;
- double z;
- } Point;
在上面的代码中,实际上完成了两个操作:
1、定义了一个新的结构类型,代码如下所示:
- struct tagPoint
- {
- double x;
- double y;
- double z;
- } ;
其中,struct 关键字和 tagPoint 一起构成了这个结构类型,无论是否存在 typedef 关键字,这个结构都存在。
2、使用 typedef 为这个新的结构起了一个别名,叫 Point,即:
- typedef struct tagPoint Point
因此,现在你就可以像 int 和 double 那样直接使用 Point 定义变量,如下面的代码所示:
- Point oPoint1={100,100,0};
- Point oPoint2;
为了加深对 typedef 的理解,我们再来看一个结构体例子,如下面的代码所示:
- typedef struct tagNode
- {
- char *pItem;
- pNode pNext;
- } *pNode;
从表面上看,上面的示例代码与前面的定义方法相同,所以应该没有什么问题。但是编译器却报了一个错误,为什么呢?莫非 C 语言不允许在结构中包含指向它自己的指针?
其实问题并非在于 struct 定义的本身,大家应该都知道,C 语言是允许在结构中包含指向它自己的指针的,我们可以在建立链表等数据结构的实现上看到很多这类例子。那问题在哪里呢?其实,根本问题还是在于 typedef 的应用。
在上面的代码中,新结构建立的过程中遇到了 pNext 声明,其类型是 pNode。这里要特别注意的是,pNode 表示的是该结构体的新别名。于是问题出现了,在结构体类型本身还没有建立完成的时候,编译器根本就不认识 pNode,因为这个结构体类型的新别名还不存在,所以自然就会报错。因此,我们要做一些适当的调整,比如将结构体中的 pNext 声明修改成如下方式:
- typedef struct tagNode
- {
- char *pItem;
- struct tagNode *pNext;
- } *pNode;
或者将 struct 与 typedef 分开定义,如下面的代码所示:
- typedef struct tagNode *pNode;
- struct tagNode
- {
- char *pItem;
- pNode pNext;
- };
在上面的代码中,我们同样使用 typedef 给一个还未完全声明的类型 tagNode 起了一个新别名。不过,虽然 C 语言编译器完全支持这种做法,但不推荐这样做。建议还是使用如下规范定义方法:
- struct tagNode
- {
- char *pItem;
- struct tagNode *pNext;
- };
- typedef struct tagNode *pNode;
3) 为数组定义简洁的类型名称
它的定义方法很简单,与为基本数据类型定义新的别名方法一样,示例代码如下所示:
- typedef int INT_ARRAY_100[100];
- INT_ARRAY_100 arr;
4) 为指针定义简洁的名称
对于指针,我们同样可以使用下面的方式来定义一个新的别名:
- typedef char* PCHAR;
- PCHAR pa;
对于上面这种简单的变量声明,使用 typedef 来定义一个新的别名或许会感觉意义不大,但在比较复杂的变量声明中,typedef 的优势马上就体现出来了,如下面的示例代码所示:
- int *(*a[5])(int,char*);
对于上面变量的声明,如果我们使用 typdef 来给它定义一个别名,这会非常有意义,如下面的代码所示:
- // PFun是我们创建的一个类型别名
- typedef int *(*PFun)(int,char*);
- // 使用定义的新类型来声明对象,等价于int*(*a[5])(int,char*);
- PFun a[5];
小心使用 typedef 带来的陷阱
接下来看一个简单的 typedef 使用示例,如下面的代码所示:
- typedef char* PCHAR;
- int strcmp(const PCHAR,const PCHAR);
在上面的代码中,“const PCHAR” 是否相当于 “const char*” 呢?
答案是否定的,原因很简单,typedef 是用来定义一种类型的新别名的,它不同于宏,不是简单的字符串替换。因此,“const PCHAR”中的 const 给予了整个指针本身常量性,也就是形成了常量指针“char*const(一个指向char的常量指针)”。即它实际上相当于“char*const”,而不是“const char*(指向常量 char 的指针)”。当然,要想让 const PCHAR 相当于 const char* 也很容易,如下面的代码所示:
- typedef const char* PCHAR;
- int strcmp(PCHAR, PCHAR);
其实,无论什么时候,只要为指针声明 typedef,那么就应该在最终的 typedef 名称中加一个 const,以使得该指针本身是常量。
还需要特别注意的是,虽然 typedef 并不真正影响对象的存储特性,但在语法上它还是一个存储类的关键字,就像 auto、extern、static 和 register 等关键字一样。因此,像下面这种声明方式是不可行的:
- typedef static int INT_STATIC;
不可行的原因是不能声明多个存储类关键字,由于 typedef 已经占据了存储类关键字的位置,因此,在 typedef 声明中就不能够再使用 static 或任何其他存储类关键字了。当然,编译器也会报错,如在 VC++2010 中的报错信息为“无法指定多个存储类”。
@编码实践
#include <stdio.h> #define MAXSIZE 8 typedef struct { char *title; } Book[MAXSIZE]; int main(void) { Book book; book[0].title="t0"; book[1].title="t1"; printf("%s,",book[0].title); printf("%s",book[1].title); return 0; }
ok
Book是类型是数组,成员类型为结构体
#include <stdio.h> #define MAXSIZE 8 typedef struct { char *title; } Book[MAXSIZE]; Book manyBooks; int main(void) { Book book; book[0].title="t0"; book[1].title="t1"; printf("%s,",book[0].title); printf("%s",book[1].title); manyBooks[0].title="mt0"; manyBooks[1].title="mt1"; printf("\n%s,",manyBooks[0].title); printf("%s",manyBooks[1].title); return 0; }
注意单复数命名的错误;
t0,t1
mt0,mt1
--------------------------------
Process exited after 0.01014 seconds with return value 0
请按任意键继续. . .
typedef关键字与结构体、结构体指针的定义 - 一路洒满阳光! - CSDN博客 https://blog.csdn.net/u013632190/article/details/47720703
#include <stdio.h> typedef struct st { int data; } alias; int main(void) { alias a; a.data=123; printf("%d",a.data); return 0; } #include <stdio.h> typedef struct st { int data; } st; int main(void) { st a; a.data=456; printf("%d",a.data); return 0; }
Self Referential Data Structure in C - create a singly linked list http://www.how2lab.com/programming/c/link-list1.php
结构体的自引用
两种定义方式
typedef struct node_type {
int data;
struct node_type *next;
} list;
struct node_type {
int data;
struct node_type *next;
};
typedef struct node_type list;