为什么这里 typedef 不起作用?

4

我知道typedef的简单定义:

typedef is a keyword in C to assign alternative names to types.

根据这个定义,我尝试按照以下方式实现typedef:

int main()
{
    typedef long mylong; //as per my knowledge after this statement mylong will be treated as long
    
    int long b;  // this works fine
    int mylong c; // but this gives error
}

我在gcc上尝试了这个。以下是错误信息:



enter image description here

我知道这个错误的意思是我没有理解typedef的实际概念。请问有人能告诉我我错在哪里吗?


你只是点赞了一个错误的答案。 - Vlad from Moscow
为什么?请解释一下,我接受了两三个回答都说了相同的事情,但这个对我解释得更多。有什么问题吗? - A.s. Bhullar
我向您展示了允许使用的类型说明符集合列表。例如,您可以编写long或int long。因此,您的问题是合理的。实际上,您可以编写typedef long my_long;然后int my_long。在这种情况下,您将把类型说明符long替换为int long。您可以使用long或int long,不是吗?所以原因很简单:标准不允许这样做。typedef被视为一个单独的类型说明符,不包含在任何类型说明符集合中。 - Vlad from Moscow
你的意思是 typedef long mylong; 不同于 typedef long int mylong 吗,正如回答所说的那样? - A.s. Bhullar
不,我想说的是typedef附加了允许的类型说明符列表。它不包含在列表的任何多重集合中。它在列表中添加了一行。因此,它并不像关键字long那样只是一个别名。如果是这样,你确实可以写int my_long。 - Vlad from Moscow
4个回答

7
与 #define 不同,typedef 是一种引入类型新名称的机制,而不是一种文本替换。
回想一下,类型 long int、int long 和 long 是三个指向相同 C 类型的同义词。使用 typedef 时,您会创建另一个指向同一类型的同义词。
当您像这样使用它时:
mylong x = 123;

使用正确: mylong被用作一种类型的名称。但是,当您尝试将它与int结合使用时,就像这样
int mylong x = 123;

编译器报错是因为 int mylong 不是一个有效的类型名称。对于编译器来说,它看起来就像你写了 int float x = 5 或者 struct mystruct int z = ... 一样。

3
根据C标准第6.7.2节的第2段(约束条件),每个类型说明符列表应该是以下多重集之一...
— void
— char
— signed char
— unsigned char
— short, signed short, short int, or signed short int
— unsigned short, or unsigned short int
— int, signed, or signed int
— unsigned, or unsigned int
— long, signed long, long int, or signed long int
— unsigned long, or unsigned long int
— long long, signed long long, long long int, or
signed long long int
— unsigned long long, or unsigned long long int
— float
— double
— long double
— _Bool
— float _Complex
— double _Complex
— long double _Complex
— atomic type specifier
— struct or union specifier
— enum specifier
— typedef name

正如您所看到的,C标准不允许将typedef name与其他类型说明符组合在一起。

这意味着我只能单独使用typedef名称,而不能将其与其他数据类型结合使用? - A.s. Bhullar
一个惊人的事情是,当我改变 mylong int c 和 int mylong c 的顺序时,它会给我不同的错误,你懂的吗? - A.s. Bhullar
@A.s. Bhullar 这取决于编译器如何解析一种构造,将选择哪个语法规则。例如,您可以编写 typedef long my_long;int main(void) { int my_long = 0; - Vlad from Moscow

3

如果在C中省略类型,则默认为int

因此:typedef long mylong;typedef long int mylong;相同。

将有问题的代码行更改为以下内容:

int long int c;

因此,出错了。
typedef是一个新类型*(不是long的文本替换)。因此,您无需添加int以创建该类型的变量。一个简单的mylong c;就足够了。
*嗯,它比那个复杂一些。新类型实际上与常规的long int相同,两者可以互换。但为了良好的域逻辑,您应将其视为一个新的单独类型。

但是当我直接尝试写int long int c;时,会出现“声明中有两个或多个数据类型”的错误,这与typedef的错误不同。 - A.s. Bhullar
2
这是因为这个解释是不正确的。typedef 不是一个简单的预处理器替换。 - Karoly Horvath
@A.s.Bhullar,这个问题是一样的。您给变量命名了两种类型,只是在不同的解析规则下出现错误。 - StoryTeller - Unslander Monica
@StoryTeller 谢谢你的清晰解释。但是如果 int long int c; 和 int mylong c; 是同一件事,那么编译器应该对这两个语句都给出相同的错误提示。不是吗? - A.s. Bhullar
@A.s.Bhullar,不是的。这两者在概念上是相同的,但其中一个涉及的机制比另一个多。 - StoryTeller - Unslander Monica
所以我在理解typedef时并没有错,实际上我在理解数据类型方面出了问题。我担心自己不了解C数据类型,因为我的实习还在前面。 - A.s. Bhullar

2
你误解了 long / short 的含义。
typedef long mylong;

你说“typedef是C语言中用来给类型分配别名的关键字。” long 实际上不是一个类型,long int 是一个类型。 C语言只允许在使用 shortlong 或者 long long 时省略掉 int。因此你的表述等同于:
typedef long int mylong;

什么?long不是一种类型,但我已经读了很多把long和int视为不同类型的教材。 - A.s. Bhullar
@A.s.Bhullar,它们是不同的类型。long int是一种类型,int是另一种类型,而short int则是另一种类型。它们之间经常进行隐式转换,但它们是不同的。大多数人省略了long中的int,因为在只有long修饰符存在时,C假定为int类型。 - StoryTeller - Unslander Monica
@StoryTeller 谢谢您的快速回答 ^°^ - ikh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接