参考文献:<<StandardC99>>
红色为本人注解,其他为原文
6.7.7 Type definitions
Syntax
1 typedef-name:
identifier
Constraints
2 If a typedef name specifies a variably modified type then it shall have block scope.
Semantics
3 In a declaration whose storage-class specifier is typedef, each declarator defines an
identifier to be a typedef name that denotes the type specified for the identifier in the way
described in 6.7.5. Any array size expressions associated with variable length array
declarators are evaluated each time the declaration of the typedef name is reached in the
order of execution. A typedef declaration does not introduce a new type, only a
synonym for the type so specified. That is, in the following declarations:
typedef T type_ident;
type_ident D;
type_ident is defined as a typedef name with the type specified by the declaration
specifiers in T (known as T), and the identifier in D has the type ‘‘derived-declaratortype-
list T ’’ where the derived-declarator-type-list is specified by the declarators of D. A
typedef name shares the same name space as other identifiers declared in ordinary
declarators.
4 EXAMPLE 1 After
typedef int MILES, KLICKSP();
typedef struct { double hi, lo; } range;
the constructions
MILES distance;
extern KLICKSP *metricp;
range x;
range z, *zp;
are all valid declarations. The type of distance is int, that of metricp is ‘‘pointer to function with no
parameter specification returning int’’, and that of x and z is the specified structure; zp is a pointer to
such a structure. The object distance has a type compatible with any other int object.
此例中,KLICKSP代表一个类型,是一个无参数,返回值为整形的函数类型.
可以这样使用:
KLICKSP func;
即声明了一个KLICKSP类型的函数
此句相当于:
int func();
5 EXAMPLE 2 After the declarations
typedef struct s1 { int x; } t1, *tp1;
typedef struct s2 { int x; } t2, *tp2;
type t1 and the type pointed to by tp1 are compatible. Type t1 is also compatible with type struct
s1, but not compatible with the types struct s2, t2, the type pointed to by tp2, or int.
在typedef后面定义一个struct时,这个struct后面跟的就不是初始化列表了,而是定义的类型.
此例中,t1的类型是struct s1,即程序中struct s1与t1等价.
tp1的类型是指向struct s1的指针,即程序中struct s1 *a与tp1 a等价
至于在这里还能不能使用初始化列表,我也不知道,如果有高手知道的话,希望能够不吝赐教(也可以给我发邮件交流pang_shapeng@hotmail.com)
6 EXAMPLE 3 The following obscure constructions
typedef signed int t;
typedef int plain;
struct tag {
unsigned t:4;
//unsigned是类型,所以这里t是变量名
const t:5;
//const后面应该接类型,所以这里t是自定义的类型,也就是说,这一行声明了一个无名称的位段
plain r:5;
};
declare a typedef name t with type signed int, a typedef name plain with type int, and a structure
with three bit-field members, one named t that contains values in the range [0, 15], an unnamed constqualified
bit-field which (if it could be accessed) would contain values in either the range [−15, +15] or
[−16, +15], and one named r that contains values in one of the ranges [0, 31], [−15, +15], or [−16, +15].
(The choice of range is implementation-defined.) The first two bit-field declarations differ in that
unsigned is a type specifier (which forces t to be the name of a structure member), while const is a
type qualifier (which modifies t which is still visible as a typedef name). If these declarations are followed
in an inner scope by
t f(t (t));
//f是一个函数,参数是一个指向函数指针,指向一个未命名的函数,带一个未命名的类型为t的参数,返回值类型也为t
long t;
then a function f is declared with type ‘‘function returning signed int with one unnamed parameter
with type pointer to function returning signed int with one unnamed parameter with type signed
int’’, and an identifier t with type long int.
我测试证实,struct tag中的第二个t不能用直接的方法访问到的.
第一个t虽然是用unsigned声明的,但仍然可以直接将其赋值为负数,并且在内存中是补码表示:1111(binary).
再这样测试:先把r和t都赋为0再都赋为-1,分别打印出来,如下:
c0 c0 cc cc = 11000000 11000000 11001100 11001100
cf fe cc cc = 11001111 11111110 11001100 11001100
可以找出蓝色的是t,绿色的是r,黑色的是不能直接访问的t可见在使用位段时,一个字节里面是从最低位开始使用的
再都赋为4,可以看到:
c4 c8 cc cc = 11000100 11001000 11001100 11001100
so,在位段操作中,使用的是"big endian".(windows,visual studio 2005下的结果)
到这里,我又想到,C里面可以把unsigned int 当做类型来定义,那么在结构体定义中加入下面两行
unsigned plain:8;
unsigned int:8;
发现:plain是变量名,而第二行则声明了一个无名称的变量,可见typedef不是做简单的替换,具体的机理还有待研究.
7 EXAMPLE 4 On the other hand, typedef names can be used to improve code readability. All three of the
following declarations of the signal function specify exactly the same type, the first without making use
of any typedef names.
typedef void fv(int), (*pfv)(int);
void (*signal(int, void (*)(int)))(int);
fv *signal(int, fv *);
pfv signal(int, pfv);
函数的定义,最后三行等价
8 EXAMPLE 5 If a typedef name denotes a variable length array type, the length of the array is fixed at the
time the typedef name is defined, not each time it is used:
void copyt(int n)
{
typedef int B[n]; // B is n ints, n evaluated now
n += 1;
B a; // ais n ints, n without += 1
int b[n]; // a and b are different sizes
for (int i = 1; i < n; i++)
a[i-1] = b[i];
}
B是int型的数组,n在typedef这行已经确定