C / C ++中的typedef是否真的通过组合复合类型(例如int *)来创建一个NEW类型?
最近我发现我的代码中的typedef
与我提出的完全不同。 像这样的例子:
typedef int *ptype; ptype v1 = 0, v2 = 0;
结果:v1和v2都被定义为指向int
类型的指针。 但是如果你只是在第二句中用int *
替换ptype
为int *v1 = 0, v2 = 0;
或int* v1 = 0, v2 =0;
,只有v1是指针,v2是普通的int
。 似乎typedef
不做简单的替换。 更重要的是,当涉及到复杂的修饰符时:
typedef int *ptype; const ptype v3 = 0;
结果将是:v3是一个const
指针,如果我们写const int *v3 = 0;
,则不是指向const
int的指针const int *v3 = 0;
。 在上面的代码中, const
表示整个ptype
的修饰符,而不是ptype
的int
。 因此,看起来像typedef
结合了复合类型int*
并创建了一个新类型。
但是,权威的C / C ++参考网站cplusplus说“typedef不会创建不同的类型。它只创建现有类型的同义词。” 所以我真的很困惑,希望有人可以帮助解释typedef
的行为。 谢谢!
“同义词”并不意味着“文本替换”。 ptype
不是由预处理器或任何东西逐字扩展到int *
。
这意味着你可以做以下事情:
typedef int *ptype; ptype a; int *b; a = b; // OK
赋值是有效的,因为ptype
和int *
是相同的类型; 不需要类型转换或强制转换。
typedef
只允许您为现有类型指定新名称。 但是,该名称将现有类型的每个方面组合成不可分割的实体,例如ptype a, b;
相当于ptype a; ptype b;
ptype a; ptype b;
(和const ptype
表示“const pointer-to-int”,因为ptype
表示“指向int的指针”)。
换句话说,就声明事物而言, typedef
创建的新名称就像内置关键字一样,但这些名称所代表的实际类型是相同的。
当cplusplus.com说typedef
没有创建新类型时,他们的意思是,在任何可以使用ptype
值的地方,你也可以使用int*
类型的值,反之亦然。 因此,如果您定义一个带有ptype
参数的函数,则可以将其传递给int*
而不需要任何转换。
这并不意味着typedef
被实现为纯粹的文本替换,就像#define
一样。
参考C89,第3.5节,这是ptype v1 = 0, v2 = 0;
不等于int *v1 = 0, v2 = 0;
。 C89通知了C和C ++的更高版本,在这方面基本相同。
在ptype v1 = 0, v2 = 0;
, ptype
是“declaration-specifiers”, v1 = 0, v2 = 0
是“init-declarator-list”。 具体来说, ptype
是“类型说明符”,更具体地说,它是“typedef-name”。 因此,我们声明了两个变量( v1
和v2
),这两个变量都具有类型ptype
,这是int*
另一个名称。
在int* v1 = 0, v2 = 0
, int*
不是 “声明说明符”,因为它由一系列“类型说明符”,“存储类指定符”和“类型限定符”组成。 你可以依次查找每一个,但是所有它们组合在一起就是一个完整的关键字列表,比如static
或const
,内置类型名称,加上typedef和enum名称以及struct / union说明符。 它们不包含*
,它是复合类型语法的一部分。 所以在这种情况下, int
是“declaration-specifiers, *v1 = 0, v2 = 0
是”init-declarator list“。一旦我们分解了”init-declarator list“的语法, *
仅适用于v1
,而不是v2
。这就是它定义一个int*
和一个int
。
同样你可以写ptype *v1 = 0, v2 = 0;
,它将定义一个pytpe*
和一个ptype
。 也就是说,一个int**
和一个int*
。
const int *
vs const ptype
的语法可以得到类似的结果 – 在前者中, const
“type-qualifier”适用于int
但在后者中它适用于ptype
。