C / C ++中的typedef是否真的通过组合复合类型(例如int *)来创建一个NEW类型?

最近我发现我的代码中的typedef与我提出的完全不同。 像这样的例子:

 typedef int *ptype; ptype v1 = 0, v2 = 0; 

结果:v1和v2都被定义为指向int类型的指针。 但是如果你只是在第二句中用int *替换ptypeint *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的修饰符,而不是ptypeint 。 因此,看起来像typedef结合了复合类型int*并创建了一个新类型。

但是,权威的C / C ++参考网站cplusplus说“typedef不会创建不同的类型。它只创建现有类型的同义词。” 所以我真的很困惑,希望有人可以帮助解释typedef的行为。 谢谢!

“同义词”并不意味着“文本替换”。 ptype不是由预处理器或任何东西逐字扩展到int *

这意味着你可以做以下事情:

 typedef int *ptype; ptype a; int *b; a = b; // OK 

赋值是有效的,因为ptypeint *是相同的类型; 不需要类型转换或强制转换。

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”。 因此,我们声明了两个变量( v1v2 ),这两个变量都具有类型ptype ,这是int*另一个名称。

int* v1 = 0, v2 = 0int* 不是 “声明说明符”,因为它由一系列“类型说明符”,“存储类指定符”和“类型限定符”组成。 你可以依次查找每一个,但是所有它们组合在一起就是一个完整的关键字列表,比如staticconst ,内置类型名称,加上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