C是强类型的吗?


88

引用维基百科

支持两种隐式转换的两种常用语言是C和C ++,有时会声称它们是弱类型语言。但是,其他人则认为,这些语言对如何混合不同类型的操作数施加了足够的限制,因此应将两者视为强类型语言。

还有更明确​​的答案吗?


188
对于C程序员来说,强力打字意味着用力按压按键。
Dan Dyer

2
C在键入连续体中处于较弱的一面。但是双方都有足够的内容,您可以用任何一种方法争论。当您使用它时,您不妨问一问(vi或emacs,netbeans或eclipse等)
Cervo

4
Wikipedia的运行状况非常糟糕,以至于我不得不编辑几个Wikipedia页面。也许现在情况好一些了。也许。
诺曼·拉姆齐

40
回复:Dan的评论(应在适当的地方注明)Peter van der Linden的书“ Expert C Programming”包含以下内容:“到目前为止,许多C程序员都认为,“强类型输入仅意味着加大键盘的力度”。
Alexandros Gezerlis '12

很好的问题!
破坏者

Answers:


154

“强类型”和“弱类型”是没有广泛认可的技术含义的术语。确实具有明确含义的术语是

  • 动态类型表示在运行时将类型附加到值,并且尝试混合不同类型的值可能会导致“运行时类型错误”。例如,如果您在Scheme中尝试通过写入将1加到true,(+ 1 #t)则将导致错误。仅当您尝试执行有问题的代码时,您才会遇到错误。

  • 静态类型意味着在编译时检查类型,而没有静态类型的程序将被编译器拒绝。例如,如果在ML中您尝试通过写入将1加到true 1 + true,则该程序将被拒绝,并显示一条(可能是隐秘的)错误消息。即使可能永远不会执行代码,也始终会出现错误。

不同的人喜欢不同的系统,部分原因是他们对灵活性的重视程度以及对运行时错误的担忧程度。

有时,“强类型”用于松散地表示“静态类型”,而“弱类型”被错误地用于表示“动态类型”。术语“强类型”的更好用法是“您不能解决或破坏类型系统”,而“弱类型”则意味着“类型系统中存在漏洞”。相反,大多数具有静态类型系统的语言都存在漏洞,而许多具有动态类型系统的语言则没有漏洞。

这些术语都没有以任何方式与某种语言中可用的隐式转换数量相关联。

如果要精确地谈论编程语言,最好避免使用术语“强类型”和“弱类型”。我要说的是C是一种静态类型的语言,但存在很多漏洞。一个漏洞是您可以将任何指针类型自由转换为任何其他指针类型。您还可以通过声明具有两个成员的C联合,在所选择的任何两种类型之间创建漏洞,每种有问题的类型一个。

我在为什么解释的语言大多是鸭式而在编译时却要强类型化方面写了更多有关静态和动态类型的文章


2
您从哪里得到建议的强类型/弱类型定义(漏洞)?
Sydius

2
为什么在动态打字环境中需要一个“漏洞”?
克里斯·康威

4
@Sydius:过去20年来大部分时间都是与设计,构建和分析编程语言和类型系统的人员闲逛。那是我的带薪工作:-)
诺曼·拉姆齐

@Chris:我从未见过带有“漏洞”的动态类型语言。漏洞的常见用法是与运行时系统或OS配合使用,例如,获取原始地址并将其转换为指向行为良好的语言值的指针。您可以在动态环境中执行此操作,但我不知道有任何尝试。
Norman Ramsey,

1
@NormanRamsey我认为Chris的问题是:whereas "weakly typed" means "there are loopholes in the type system
Nir Alfasi 2014年

23

很难将每种语言分类为“弱”或“强”类型,这更像是一个连续体。但是,与其他语言相比,C是强类型的。每个对象都有一个编译时类型,如果您正在使用该类型不允许您执行的操作,编译器会(大声地)通知您。例如,您不能使用错误的参数类型来调用函数,访问不存在的struct / union成员等。

但是有一些缺点。一个主要的弱点是类型转换-它们实质上是在说您将迷惑对象的类型,并且编译器应该保持安静(如果可以的话)。 void*这也是另一个弱点-它是指向未知类型的通用指针,当您使用它们时,必须格外小心,以确保执行正确的操作。编译器无法静态检查的大多数使用void*void*还可以将其转换为指向任何类型的指针而无需强制转换(仅在C中而不在C ++中),这是另一个缺点。


不错的答案,尽管“类型转换...和编译器应该保持安静”困扰我。类型转换与关闭警告不同,它实际上会更改对所引用值的解释。
高杰夫

15
您在输入方面混淆了“静态”和“强大”。这两个概念彼此独立。
bentin

1
丹尼斯·里奇(C的作者)称C为“强类型输入和弱检查”
TimZaman

11

文献尚不清楚。我认为强类型不是肯定/否,强类型存在不同程度的差异。

编程语言对如何执行程序进行了规范。有时不清楚如何使用某些程序执行。例如,试图从数字中减去字符串的程序。或除以零的程序。有几种处理这些情况的方法。某些语言具有处理这些错误的规则(例如,它们引发异常)。其他语言只是没有规则来处理这些情况。这些语言通常具有类型系统,以防止编译导致未指定行为的程序。还有一些语言具有未指定的行为,并且没有防止在编译时出现这些错误的类型系统(如果编写的程序遇到未指定的行为,则可能会发射导弹)。

所以:

指定在每种情况下在运行时会发生什么情况的语言(如在字符串中添加数字)称为动态类型。防止在编译时执行带有错误的程序的语言是静态类型的。未指定发生情况且也没有防止错误的类型系统的语言称为弱类型。

Java是静态类型的吗?是的,因为其类型系统不允许从数字中减去字符串。不可以,因为它允许您除以零。您可以使用类型系统在编译时防止被零除。例如,通过创建一个不能为零的数字类型(例如NonZeroInt),并且只允许除以具有该类型的数字。

那么C是强类型还是弱类型?C是强类型的,因为类型系统不允许某些类型错误。但是在其他情况下,如果未定义会发生什么,它的类型就会很弱(并且类型系统无法保护您)。


我喜欢将动态和静态结合为强和弱的形式。但是,我不确定我对静态类型的系统停止除以零的观点。如果我的静态类型int从用户或命令行参数或文件中获取值,则编译器无法采取任何措施阻止它成为零!
瑞奇(Rikki)

1
有静态类型系统可以防止这种情况,但是大多数语言相对于零除都是弱类型或动态“类型化”,因为这是未定义的行为(C)或引发异常(Java)。
Jules

11

C被认为是弱类型的,因为您可以通过强制转换将任何类型转换为任何其他类型,而不会产生编译器错误。您可以在此处阅读有关此问题的更多信息。


2
维基百科在这里具有误导性。C是强类型的,类型非常有效,如果您弄错了它们,编译器会拒绝,但是,C还提供了一些功能来绕过它。与仅具有“字节”类型的BCPL之类的语言进行比较。
gbjbaanb

12
弱类型并不意味着一种语言没有任何类型,它只是意味着可以将类型从一种类型隐式地强制转换为另一种类型。与Python相比,Python是一种强类型语言,您必须在其中使用函数调用显式转换类型。
mipadi

能够在C中强制转换事物也有助于使其成为弱类型。我有永远的疑问
Suraj Jain

8

C比Javascript更强类型,而Ada不那么强类型。

我会说它更多地属于连续体的强类型方面。但其他人可能会不同意(即使他们错了)。

到底是怎么回事?


这是有点开玩笑的答案。但是,请详细说明错误。
Michael Burr

1
JavaScript是强类型的。它只是不是静态输入的。所有类型检查都在运行时发生(动态的,不是静态的),但它们确实会发生,并且这样做会阻止您破坏内存(强类型化的一个方面)。
bentin

5
好吧,正如Norm Ramsey的很好回答所表明的那样,“强类型”和“弱类型”并不是特别明确的术语。同样,就强类型键入Javascript而言,有些人可能认为(“ 4” /“ 2”)是有效的Javascript表达式可能表示相反。
Michael Burr

5

C被视为静态类型(不能将变量从int更改为float)。声明变量后,该变量将被卡住。

但由于类型可以翻转,因此被认为是弱类型的。

什么是0?'\ 0',FALSE,0.0等。

在许多语言中,您不能说IF(变量),因为条件只会从布尔表达式中获取布尔值。这些是更强类型的。字符和整数之间的转换也是如此。

基本上,c具有两种主要的简单数据类型,即整数和浮点数(尽管精度各不相同)。其他所有布尔值,枚举(不简单,但很合适)等都被实现为其中之一。偶数字符基本上是整数。

与其他具有字符串类型的语言相比,只能将枚举类型分配给已定义的值的布尔类型,仅可以使用生成布尔值或true / false的表达式的布尔类型。

但是您可以辩称,与Perl C相比,它是强类型的。因此,它是那些著名的参数之一(vi vs emacs,linux vs Windows等)。C#比C具有更强的类型。基本上,您可以使用任何一种方法进行争论。而且您的答案可能会双向:)还有一些教科书/网页会说C是弱类型的,而有些会说C是强类型的。如果您去维基百科,那么C条目将显示“部分弱类型”。我要说比起Python C是弱类型的。因此,在连续体上使用Python / C#,C,Perl。


请解释你的理由是Perl较少强类型比C
user51568

打印“ Testing” + 0#perl将执行0; $ var =“字符串”; $ var = 1; $ var = 123.4; 这是什么变量?
Cervo

在C中char * test =“ testing”; printf(测试+ 0); 仍然是一个字符串,只是在C中,如果我使用数字而不是零,则索引将发生变化。它仍然很弱,但是比perl强一些。char *测试;测试= 0; 测试= 123.4; test =“ c”; ...我的编译器生成错误
Cervo

该错误表明需要强制转换。它的类型检查仍然比Perl强,因此在连续性上,我不得不说C比Perl更强类型。您仍然可以进行test =(char *),然后使用0、123.4,'C'等。但是仅仅这样做是错误的。
Cervo

4

这里有很多好的答案。我想提出真实世界Haskell的一个重要观点:

意识到许多语言社区都有自己的“强类型”定义是很有用的。不过,我们将简要地和广泛地谈谈类型系统中的强度概念。

(剪断)

围绕类型系统的烟花源于普通英语,人们在其中将“弱”和“强”一词视为价值观念:我们通常认为强胜于弱。与学术术语相比,有更多的程序员说普通话,而且很多时候,学者们确实在为任何不适合他们的幻想的类型系统投掷砖瓦。结果常常是流行的互联网消遣,一场火焰大战。

因此,请查看有关C和C ++的答案,但请记住,“强”和“弱”不会映射为“好”和“坏”。


4

根据Dennis Ritchie(C的创建者)和Brian Kernighan的说法,C不是强类型语言。以下几行摘自《 C编程语言》第3页第5段

C不是强类型语言,但随着它的发展,其类型检查得到了加强。


3

在我看来,C / C ++是强类型的。由于C与机器的距离太近,允许类型转换(hack *)的hack种类就在那里。换句话说,您可以从Pascal调用汇编程序命令并操纵指针,而Pascal仍被视为强类型语言。您可以通过JNI从Java调用汇编程序和C可执行文件,但这不会使Java弱类型化。

C只是在其中使用原始指针等将汇编器“嵌入”其中。


3

术语强类型没有一个商定的定义。因此,除非您定义“强类型”的含义,否则无法回答您的问题。

在我的经验中,术语“强类型”和“弱类型”使用专门的巨魔,由于缺乏定义允许巨魔重新定义他们中间参数,以满足他们的议程。除了启动火焰战争外,这些术语几乎没有用。

您可能还想看看强类型语言的主要方面是什么?在StackOverflow上。


3
我不同意。“强类型”是指可以确定值的数据类型,并且仅允许使用适合该类型的操作。可以确定时“动态地”和“静态地”处理。
joel.neely,2009年

2
确实具有讽刺意味,试图通过引入另一个定义来反驳没有统一定义的说法,对吗?
约尔格W¯¯米塔格

1
@Jorg:不打算介绍另一个;只是说明我移动的圈子中常用的那个。
joel.neely,2009年

1

在“弱类型”和“强类型”之间存在一个具有多个并行途径的连续体,这两个术语甚至都没有很好地定义。

C是静态类型的,因为编译器知道每个局部变量和struct成员的声明类型。

如果每个对象都有特定的类型,但动态类型化的语言可能仍会强类型化,但编译器无法知道该类型。


0

您查询的原因是什么?我要问的原因是,这是一个微小的差异,您对“强类型”的特定用法可能需要或多或少地加以说明。我肯定会说Java和其他语言对隐式类型对话有更严格的限制。


大多出于好奇,但我正在申请C职位,并想知道以防他们向我提问。
Sydius

那么,更长的答案可能是最好的方法,而不是仅仅说“是”或“否”。
BobbyShaftoe

0

当没有“强类型”的具体定义时,很难提供具体的答案。我会说C是强类型化的,因​​为每个变量和每个表达式都有一个类型,但是弱类型化的C是允许您使用强制转换来更改类型并将一种类型的表示形式重新解释为另一种类型。


有一个官方def。对于类型。它说一个系统。当保证没有运行时类型错误时,ST为ST。例如:ML,Haskell。这有助于使系统省略对象内部的类型标签,而将运算符应用于正确的类型。因为我们在执行之前就知道对象中不需要标签。由于C具有强制转换和指向任意备忘录的指针访问权限,因此C不是st
alinsoar

0

我会说C的类型与编译器/平台所指定的一样强。例如,如果您在严格的平台上构建,则取消引用类型查询指针可能会中断:

void m_free(void **p)
{
        if (*p != NULL) {
                free(*p);
                *p = NULL;
        }
}

....
char *str = strdup("foo");
m_free((void **) &foo);

现在,如果您告诉编译器跳过严格的别名,那将不是问题,但不是很容易移植。因此,从这种意义上讲,突破语言的界限是可能的,但可能不是最好的主意。这比典型的转换(即将int转换的时间长)超出了一个步骤,并且确实显示了虚假的可能陷阱之一。

因此,我想说C基本上是严格类型化的,但是它的各种编译器假定程序员最清楚并且允许一定的灵活性。这实际上取决于编译器,有些人不会选择那些潜在的哎呀。因此,从这个意义上讲,选择的编译器在回答问题时确实发挥了作用。正确的方法通常不同于编译器允许您使用的方法。



-1

没有强类型。

请考虑以下函数原型告诉您有关参数的数据类型的信息:

void func (int n, char ch, ...);

没有。因此,我建议强类型不适用于此处。


??它告诉您有一个int,然后是一个char,然后是任意数量的任何类型的参数。那不是“没有”。
劳伦斯·多尔

...不会告诉您所传递的参数类型。的确,函数本身的类型是已知的。这就是软件猴子所说的。
Johannes Schaub-litb

我在说的是那些“任何类型的任意数量的参数”。一条链的强弱与其最弱的一环一样。
joel.neely,2009年

-3

我会说它是强烈的类型,因为每个表达式的类型都不是其值的函数;EI可以在运行时之前知道。

OTOH我不确定这是否是强类型的正确描述。我能看到的使用语言的唯一更强力的主张是,确保不能在运行时通过重新解释类型强制转换,联合,调用其他语言,指针,汇编语言等来颠覆类型系统。存在,但严重残缺,以至于除了高度保证和学术界之外,程序员似乎对它们并没有太大兴趣。正如某人所指出的那样,要真正做到这一点,您就需要具有类似nonZeroInt和诸如此类的类型。uck


3
没什么 我对强类型或C的定义?
BCS
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.