C语言是强类型语言吗?

98

引用Wikipedia的话:

支持许多种隐式转换的两种常用语言是C和C++,有时被认为这些是弱类型语言。然而,其他人则认为这些语言对不同类型的操作数如何混合使用施加了足够的限制,应将其视为强类型语言。

是否有更明确的答案?


224
对于一位C程序员而言,“强类型”意味着更加努力地按键盘上的键。 - Dan Dyer
3
在打字的连续性中,C语言属于较弱的一端。但是两端都有足够多的东西可以支持你的观点。顺便问一下(vi或emacs,netbeans或eclipse等)。 - Cervo
4
维基百科上的情况很糟糕,让我感到有必要编辑一些维基百科页面。也许现在情况稍微好了一些。也许。 - Norman Ramsey
49
回复:丹的评论(给应有的荣誉)彼得·范德林登的书《Expert C Programming》中有这样一句话:“直到今天,许多C程序员仍然认为‘强类型只是在键盘上额外用力敲打’。” - Alexandros Gezerlis
非常好的问题!!! - Destructor
显示剩余3条评论
17个回答

177
“Strongly typed” 和 “weakly typed” 这两个术语没有被广泛认同的技术含义。有明确定义的术语是:
- 动态类型:意味着类型在运行时与值相关联,并且尝试混合不同类型的值可能会导致“运行时类型错误”。例如,在 Scheme 中,如果您尝试通过编写 `(+1 #t)` 将 true 加 1,则会导致错误。只有在尝试执行有问题的代码时才会遇到错误。 - 静态类型:意味着类型在编译时进行检查,并且没有静态类型的程序将被编译器拒绝。例如,在 ML 中,如果您尝试通过编写 `1 + true` 将 true 加 1,则该程序将被拒绝并显示(可能是晦涩的)错误消息。无论代码是否被执行,都会收到错误。
不同的人根据他们对灵活性的重视程度和对运行时错误的担忧程度而喜欢不同的系统。
有时,“强类型” 被松散地用来表示 “静态类型”,“弱类型” 被错误地用来表示 “动态类型”。更好的用法是,“强类型” 表示“您不能规避或破坏类型系统”,而“弱类型” 表示“类型系统中存在漏洞”。恶意地说,大多数具有静态类型系统的语言都有漏洞,而许多具有动态类型系统的语言则没有漏洞。
这些术语与语言中可用的隐式转换数量没有任何关系。
如果您想准确地谈论编程语言,最好避免使用 “强类型” 和 “弱类型” 这些术语。我会说 C 是一种静态类型的语言,但它有很多漏洞。一个漏洞是,您可以自由地将任何指针类型强制转换为任何其他指针类型。您还可以通过声明一个 C 联合来创建两个所需类型之间的漏洞,该联合具有两个成员,每个成员对应一个所需的类型。
我在 why-interpreted-langs-are-mostly-ducktyped-while-compiled-have-strong-typing 中更详细地介绍了静态和动态类型。

2
你从哪里得到你所建议的强类型/弱类型定义(漏洞问题)? - Sydius
2
在动态类型环境中,为什么需要“漏洞”? - Chris Conway
5
@Sydius:过去20年中,我大部分时间都花在与设计、构建和分析编程语言和类型系统的人们一起。那是我的工作 :-) - Norman Ramsey
1
@NormanRamsey 我认为Chris在他的问题中指的是:“而‘弱类型’意味着‘类型系统存在漏洞’”。 - Nir Alfasi
答案是错误的,因为“破坏类型系统”与“类型不安全”有关,而不是弱类型,尽管这两者定义得很松散。 - Elazar
显示剩余5条评论

24

很难将每种语言归类为“弱类型”或“强类型” -- 这更像是一个连续的过程。但与其他语言相比,C语言具有相当强的类型化特性。每个对象都有编译时类型,如果您正在对类型不允许的对象进行操作,编译器会大声提醒您。例如,您无法使用错误类型的参数调用函数,访问不存在的结构/联合成员等。

但是这里还有一些弱点。其中一个主要弱点是类型转换 - 它们基本上表示您将要处理对象的类型,并且编译器应该保持安静(如果可以)。 void*也是另一个弱点--它是指向未知类型的通用指针,当您使用它们时,必须格外小心以确保正确性。大多数情况下,编译器无法静态检查void*的使用方式。在C中,void*也可以转换为任何类型的指针而无需转换(但在C++中不行),这是另一个弱点。


不错的回答,尽管“类型转换...编译器应该保持安静”让我感到困扰。类型转换不像关闭警告一样,它实际上改变了所引用值的解释。 - Tall Jeff
18
你在关于类型化的问题上混淆了“静态”和“强类型”的概念。这两个概念彼此独立。 - bendin
2
Dennis Richie(C语言的作者)称C语言为“强类型且弱检查”。 - TimZaman

15

C语言被认为是弱类型语言,因为你可以通过转换将任何类型转换为另一种类型而不会触发编译器错误。您可以在此处了解更多相关信息。


3
维基百科在这里存在误导。C语言是强类型的,类型非常严格,如果您类型错误,编译器将会报错。不过,C语言也提供了一些特性,可以让您绕过此限制。与只有“byte”类型的BCPL等语言相比较。 - gbjbaanb
16
弱类型并不意味着一种语言没有任何类型,它只是意味着类型可以从一种类型隐式地转换为另一种类型。与之相比,Python是一种强类型语言,你必须通过函数调用来显式地转换类型。 - mipadi
能否在C语言中进行强制类型转换也会导致它成为弱类型吗?我一直有这个疑问。 - Suraj Jain

11

文献对此并不清楚。我认为强类型并非是只有是/否的问题,而是有不同程度的强类型。

编程语言规定了如何执行程序。有时候在执行某些程序时并不清楚该怎么做。例如,试图从数字中减去一个字符串的程序或者除以零的程序。有多种方法来处理这些情况。一些语言有处理这些错误的规则(例如,抛出异常)。其他语言则没有处理这些情况的规则。那些语言通常会有类型系统来防止编译导致未指定行为的程序。也存在一些语言,它们具有未指定的行为,并且没有类型系统来在编译时防止这些错误(如果您编写了一个触发未指定行为的程序,它可能会发射导弹)。

所以:

在每种情况下具体规定运行时操作的语言(例如将数字加到字符串上)称为动态类型。 在编译时防止执行带有错误的程序的语言称为静态类型。 既不具体说明会发生什么,也没有类型系统来防止错误的语言称为弱类型。

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

C语言是强类型还是弱类型呢? C语言的类型系统不允许某些类型错误,所以它是强类型。但在其他情况下,当发生未定义的情况时(而类型系统不能保护您)它是弱类型。


我喜欢你将动态和静态对齐作为强类型和弱类型的形式。然而,我不确定你关于静态类型系统阻止除零操作的观点。如果我的静态类型“int”从用户、命令行参数或文件中获取一个值,编译器无法阻止它成为零! - Rikki
1
有一些静态类型系统可以防止这种情况发生,但大多数语言在除以零方面要么是弱类型的,要么是动态类型的,因为它是未定义的行为(C),或者它们会抛出异常(Java)。 - Jules

7

据C语言的创造者Dennis Ritchie和Brian Kernighan所说,C语言并非强类型语言。以下内容摘自《C程序设计语言》第3页第5段。

C语言并非强类型语言,但随着其发展,其类型检查已得到加强。


7

C语言比Javascript更强类型,但比Ada弱一些。

我认为它更偏向于强类型的一侧,但其他人可能会持不同意见(即使他们是错的)。

这样的定义还算准确吗?


这是一个有点玩笑式的回答。但请详细说明错误之处。 - Michael Burr
2
JavaScript是一种强类型语言,只是它不是静态类型的。所有类型检查发生在运行时(动态而非静态),但它们确实发生,并且可以防止你破坏内存(这是强类型的一个方面)。 - bendin
5
正如Norm Ramsey的非常好的回答所指出的那样,“strongly typed”和“weakly typed”这两个术语并没有特别清晰的定义。至于JavaScript是否强类型语言,一些人可能会认为(“4”/“2”)作为一个有效的JavaScript表达式可能表明了相反的情况。 - Michael Burr

5

C被认为是静态类型的(变量不能从int更改为float)。一旦变量被声明,它就会保持不变。

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

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

在许多语言中,您不能说IF(variable),因为条件只会从布尔表达式中获取布尔值。这些更加强类型化。同样适用于字符和整数之间的转换。

基本上,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 = "string"; $var = 1; $var = 123.4; 它是什么类型的变量? - Cervo
在C语言中,char *test = "testing"; printf(testing + 0);仍然是一个字符串,只是如果我使用数字而不是零,索引会改变。它仍然相当薄弱,但比Perl要强一些。char *test; test=0; test = 123.4; test = "c";...我的编译器会生成错误。 - Cervo
错误提示需要进行强制类型转换。尽管如此,相对于Perl来说,它是更强的类型检查,所以在这个连续性上,我必须说C比Perl更强类型。你仍然可以使用test =(char *)并使用0、123.4、'C'等,但是如果只是这样做,那么就会出现错误。 - Cervo

5
这里有很多好的答案。我想从Real World Haskell中提出一个重要观点: “强类型”的定义因语言社区而异,了解类型系统中的“强度”概念非常有用。
(省略)
关于类型系统的争论源于普通英语,人们将“弱”和“强”这些词与价值观联系起来:我们通常认为强大优于虚弱。许多程序员使用的是普通英语而不是学术术语,而且学者们经常会对他们不喜欢的任何类型系统进行批评。结果往往是互联网上流行的消遣活动,火药味十足的战争。
所以,请看看关于C和C ++的答案,但请记住,“强”和“弱”并不代表“好”和“坏”。

3

在我看来,C/C++是强类型语言。允许类型转换(void*)的黑客方式之所以存在,是因为C接近于机器。换句话说,你可以从Pascal调用汇编命令并操纵指针,但Pascal仍被视为强类型语言。你可以通过JNI从Java调用汇编和C可执行文件,但这并不意味着Java是弱类型语言。

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


2
“强类型”这个术语没有一个公认的定义。因此,除非您定义了“强类型”的含义,否则无法回答您的问题。
根据我的经验,“强类型”和“弱类型”这些术语被 trolls(指在网络上故意制造争端和不良氛围的人)所使用,因为它们缺乏明确定义,这使得 trolls 可以在争论中重新定义它们以适应他们的议程。除了用于引发争吵外,这些术语几乎没有什么用处。
您还可以查看 StackOverflow 上的 What are the key aspects of a strongly typed language?

4
我不同意。"强类型"意味着可以确定一个值的数据类型,并且只允许适合该类型的操作。 "动态"和"静态"是用来表示这种确定何时发生的。 - joel.neely
3
确实意识到试图反驳对“没有共识定义”的说法时,引入另一个定义的讽刺之处,对吗? - Jörg W Mittag
1
@Jorg:我并不是在介绍另一个,只是在陈述我所处圈子中常用的一个。 - joel.neely

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