C 是强类型的吗?
引用维基百科:
两种常用语言 支持多种隐式 转换是C和C++,它是 有时声称这些是 弱类型语言。 然而, 其他人则认为这些语言 对如何进行足够的限制 不同类型的操作数可以是 混合,两者应该被视为 作为强类型语言。
有没有更明确的答案?
To quote Wikipedia:
Two commonly used languages that
support many kinds of implicit
conversion are C and C++, and it is
sometimes claimed that these are
weakly typed languages. However,
others argue that these languages
place enough restrictions on how
operands of different types can be
mixed, that the two should be regarded
as strongly typed languages.
Is there a more definitive answer?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(18)
不是强类型的。
考虑以下函数原型告诉您有关参数数据类型的信息:
Nothing。 所以我建议强类型在这里不适用。
Not strongly typed.
Consider what the following function prototype tells you about the data types of the arguments:
Nothing. So I suggest that strong typing does not apply here.
强类型的“经典”定义是,语言强制程序员明确地告诉编译器每个变量的类型,以便它可以确保您获得的行为是您所期望的。 其目的是在尝试运行代码之前检测并报告整类问题。
运行时检测此类问题的问题在于,大多数代码包含不经常运行的行,特别是那些设计用于错误检查的行。 这些可能很少运行,以至于原始程序员从未发现某些类型问题,因此逃逸到生产中。 通过编写一个彻底的测试平台来测试每个函数中的每一行代码可以避免这种情况,但我很少看到这样做。
有些人用《C 编程语言》一书作为参考,来判断作者是否认为 C 是强类型的。 这是误导性的。 本书撰写时,C 类型检查与采用 C 标准时不同。 随着时间的推移,C 类型检查变得更加严格,并且隐式类型转换的行为现在已在标准中详细说明。
C 中提供了强制转换和 void 指针作为绕过类型检查的显式方法。 用它们来证明 C 是松散类型的是不诚实的。 它忽略了语言中仅用于定义类型和强制一致性的整个部分,因为存在解决方法。 这就像说安全带毫无价值,因为有些人不使用它们。 即使使用强制转换和 void 指针,仍然需要 tupe 定义,仍然检查类型,并且捕获绝大多数代码行的类型错误,我认为更公平的说法是 C 是一种强类型语言,其机制允许知识渊博的用户如果他们认为需要的话,可以绕过类型检查。
The “classic” definition of strongly typed is that the language forces the programmer to be explicit in telling the compiler the tupe of each variable so that it can ensure the behavior you get is what you expected. Its purpose is to detect and report an entire class of problems prior to attempting to run the code.
The problem with runtime detection of such problems is that most code contains infrequently run lines, particularly those designed for error checking. These may be run so rarely that some type problems are never seen by the original programmer and as a result escape into production. This can be avoided by writing a thorough test bench that exercises every line of code in every function, but I’ve rarely seen that done.
Some people are using the C Programming Language book as a reference as to whether the author thought C was strongly typed. This is misleading. When the book was written Cs type checking was not the same as it was when the C standard was adopted. C type checking became more strict over time and the behavior of implicit type conversions is now thoroughly spelled out in the standard.
Casts and void pointers are provided in C as an explicit way to bypass the type checking. Using them as proof C is loosely typed is disingenuous. It dismisses the entire part of the language that exists solely to define types and enforce consistency on the grounds there’s a workaround. It’s like saying seatbelts are worthless because some people don’t use them. Even with casts and void pointers, tupe definitions are still required, types are still checked, and type errors caught for the vast majority of lines of codes I think it’s fairer to say C is a strongly typed language with mechanisms to allow the knowledgeable user to bypass type checking should they feel they need to do so.
您查询的原因是什么? 我问的原因是这是一个微小的差异,您对“强类型”的特定用法可能需要或多或少的澄清。 我肯定会说 Java 和其他语言对隐式类型对话有更严格的限制。
What is the reason for your query? The reason I ask is this is sort of a minor difference and your particular usage of "strongly-typed" might need more or less clarification. I would definitely say that Java and other languages have tighter restrictions on implicit type conversation.
当“强类型”没有具体的定义时,很难提供具体的答案。 我想说 C 是强类型的,因为每个变量和每个表达式都有一个类型,但弱类型是因为它允许您使用强制转换来更改类型并将一种类型的表示重新解释为另一种类型。
It is difficult to provide a concrete answer when there isn't a concrete definition of "strongly typed". I would say that C is strongly typed in that every variable and every expression has a type but weakly typed in that it allows you to change types using casts and to reinterpret the representation of one type as another.
c 是弱类型,b 是无类型。
c is weakly typed, b is typeless.
我想说它是强类型,因为每个表达式都有一个不是其值的函数的类型; ei 它可以在运行之前知道。
OTOH 我不确定这是否是强类型的正确描述。 我认为一种语言做出的唯一更有力的声明是保证你不能在运行时通过重新解释类型转换、联合、调用其他语言、指针、汇编语言等来破坏类型系统。存在但非常严重,以至于高可靠性和学术界之外的程序员似乎对它们没有太大兴趣。 正如某人所指出的,要真正做到这一点,您开始需要拥有诸如
nonZeroInt
之类的类型。 恶心。I'd say it is strongly types as every expression has a type that is not a function of it's value; e.i. it can be known before runtime.
OTOH I'm not sure that is the correct description of strongly typed. The only stronger claim I can see reason for a language to make would be the assurance that you can't subvert the type system at runtime via reinterpret type casts, unions, calling into other languages, pointers, assembly language, etc. Languages like this exist but are so crippled that they seem to not be of much interest to programmers outside of high assurance and academia. As pointed out by someone, to really do that right you start needing to have types like
nonZeroInt
and whatnot. Yuck.“强类型”和“弱类型”是没有广泛商定的技术含义的术语。 确实具有明确定义含义的术语是
动态类型意味着类型在运行时附加到值,并且尝试混合不同类型的值可能会导致“运行时类型错误”。 例如,如果在Scheme中您尝试通过编写
(+ 1 #t)
来将1添加到true,这将导致错误。 仅当您尝试执行有问题的代码时才会遇到错误。静态类型意味着在编译时检查类型,不具有静态类型的程序会被编译器拒绝。 例如,如果在 ML 中您尝试通过编写
1 + true
将 1 添加到 true,则程序将被拒绝,并显示一条(可能是神秘的)错误消息。 即使代码可能永远不会被执行,您也总是会收到错误。不同的人喜欢不同的系统,部分取决于他们对灵活性的重视程度以及对运行时错误的担心程度。
有时,“强类型”被宽松地用来表示“静态类型”,而“弱类型”被错误地用来表示“动态类型”。 “强类型”一词的更好用法是“你无法绕过或颠覆类型系统”,而“弱类型”意味着“类型系统中存在漏洞”。 相反,大多数具有静态类型系统的语言都存在漏洞,而许多具有动态类型系统的语言则没有漏洞。
这些术语与语言中可用的隐式转换的数量没有任何关系。
如果您想精确地谈论编程语言,最好避免使用“强类型”和“弱类型”这些术语。 我想说 C 是一种静态类型语言,但有很多漏洞。 一个漏洞是您可以自由地将任何指针类型转换为任何其他指针类型。 您还可以通过声明一个具有两个成员的 C 联合体,在您选择的任意两种类型之间创建一个漏洞,每个成员对应一个相关类型。
我在 为什么解释语言大部分都是鸭类型,而编译语言却具有强类型。
"Strongly typed" and "weakly typed" are terms that have no widely agreed-upon technical meaning. Terms that do have a well-defined meaning are
Dynamically typed means that types are attached to values at run time, and an attempt to mix values of different types may cause a "run-time type error". For example, if in Scheme you attempt to add one to true by writing
(+ 1 #t)
this will cause an error. You encounter the error only if you attempt to execute the offending code.Statically typed means that types are checked at compile time, and a program that does not have a static type is rejected by the compiler. For example, if in ML you attempt to add one to true by writing
1 + true
, the program will be rejected with a (probably cryptic) error message. You always get the error even if the code might never be executed.Different people prefer different systems according in part to how much they value flexibility and how much they worry about run-time errors.
Sometimes "strongly typed" is used loosely to mean "statically typed", and "weakly typed" is used incorrectly to mean "dynamically typed". A better use for the term "strongly typed" is that "you cannot work around or subvert the type system", whereas "weakly typed" means "there are loopholes in the type system". Perversely, most languages with static type systems have loopholes, while many languages with dynamic type systems have no loopholes.
None of these terms are connected in any way with the number of implicit conversions available in a language.
If you want to talk precisely about programming languages, it is best to avoid the terms "strongly typed" and "weakly typed". I would say that C is a language that is statically typed but that has a lot of loopholes. One loophole is that you can freely cast any pointer type to any other pointer type. You can also create a loophole between any two types of your choice by declaring a C union that has two members, one for each of the types in question.
I have written more about static and dynamic typing at why-interpreted-langs-are-mostly-ducktyped-while-compiled-have-strong-typing.
很难将每种语言分为“弱”类型或“强”类型——它更像是一个连续体。 但是,与其他语言相比,C 是相当强类型的。 每个对象都有一个编译时类型,如果您正在对对象执行其类型不允许您执行的操作,编译器会(大声)让您知道。 例如,您无法使用错误类型的参数调用函数,无法访问不存在的结构/联合成员等。
但也有一些弱点。 一个主要的弱点是类型转换——它们本质上是说你将要处理对象的类型,并且编译器应该保持安静(如果可以的话)。
void*
也是另一个弱点——它是一个指向未知类型的通用指针,当你使用它们时,你必须格外小心,确保你做的是正确的事情。 编译器无法静态检查void*
的大多数使用。void*
还可以在不进行强制转换的情况下转换为任何类型的指针(仅在 C 中,在 C++ 中不行),这是另一个弱点。It's hard to classify every language into 'weakly' or 'strongly' typed -- it's more of a continuum. But, in comparison to other languages, C is fairly strongly typed. Every object has a compile-time type, and the compiler will let you know (loudly) if you're doing something with an object that its type doesn't let you do. For example, you can't call functions with the wrong types of parameters, access struct/union members which don't exist, etc.
But there are a few weaknesses. One major weakness is typecasts - they essentially say that you're going to be mucking around with the types of objects, and the compiler should be quiet (when it can).
void*
is also another weakness -- it's a generic pointer to an unknown type, and when you use them, you have to be extra careful that you're doing the right thing. The compiler can't statically check most uses ofvoid*
.void*
can also be converted to a pointer to any type without a cast (only in C, not in C++), which is another weakness.C 被认为是弱类型的,因为您可以通过强制转换将任何类型转换为任何其他类型,而不会出现编译器错误。 您可以在此处了解有关该问题的更多信息。
C is considered to be weakly typed, because you can convert any type to any other type through a cast, without a compiler error. You can read more about the issue here.
文献对此并不清楚。 我认为强类型不是是/否,强类型有不同程度的。
编程语言有一个关于如何执行程序的规范。 有时不清楚如何执行某些程序。 例如,尝试从数字中减去字符串的程序。 或者除以零的程序。 有几种方法可以处理这些情况。 有些语言有处理这些错误的规则(例如它们抛出异常)。 其他语言只是没有处理这些情况的规则。 这些语言通常具有类型系统来防止编译导致未指定行为的程序。 而且还存在具有未指定行为的语言,并且没有类型系统来在编译时防止这些错误(如果您编写的程序遇到未指定行为,它可能会发射导弹)。
因此:
指定每种情况下运行时发生的情况(例如将数字添加到字符串中)的语言称为动态类型。
防止在编译时执行有错误的程序的语言是静态类型的。
不指定发生的情况并且也没有类型系统来防止错误的语言称为弱类型。
那么Java是静态类型的吗? 是的,因为它的类型系统不允许从数字中减去字符串。 不,因为它允许您除以零。 您可以使用类型系统来防止在编译时被零除。 例如,通过创建不能为零的数字类型(例如 NonZeroInt),并且只允许除以具有此类型的数字。
那么C是强类型还是弱类型呢? C 是强类型的,因为类型系统不允许某些类型错误。 但在其他情况下,当未定义发生的情况时(并且类型系统无法保护您),它是弱类型的。
The literature isn't clear about this. I think that strongly typed isn't yes/no, there are varying degrees of strong typing.
A programming language has a specification of how it executes programs. Sometimes it's not clear how to execute with certain programs. For example, programs that try to subtract a string from a number. Or programs that divide by zero. There are several ways to deal with these conditions. Some languages have rules for dealing with these errors (for example they throw an exception). Other languages just don't have rules to deal with these situations. Those languages generally have type systems to prevent compiling programs that lead to unspecified behavior. And there also exist languages that have unspecified behavior and don't have a type system to prevent these errors at compile time (if you write a program that hits unspecified behavior it might launch the missiles).
So:
Languages that specify what happens at runtime in every case (like adding a number to a string) are called dynamically typed.
Languages that prevent executing programs with errors at compile time are statically typed.
Languages that don't specify what happens and also don't have a type system to prevent errors are called weakly typed.
So is Java statically typed? Yes, because its type system disallows subtracting a string from a number. No, because it allows you to divide by zero. You could prevent division by zero at compile time with a type system. For example by creating a number type that can't be zero (e.g. NonZeroInt), and only allow to divide by numbers that have this type.
So is C strongly typed or weakly typed? C is strongly typed because the type system disallows some type errors. But it's weakly typed in other cases when it's undefined what happens (and the type system doesn't protect you).
C 的类型比 Javascript 强,但比 Ada 的类型弱。
我想说它更多地属于连续体的强类型方面。 但其他人可能不同意(即使他们错了)。
怎么样才算是确定呢?
C is more strongly typed than Javascript and less strongly typed than Ada.
I'd say it falls more into the strongly typed side of the continuum. but someone else might disagree (even if they're wrong).
How's that for definitive?
根据 Dennis Ritchie(C 的创建者)和 Brian Kernighan 的说法,C 不是强类型语言。 以下几行摘自《C 编程语言》一书第 3 页第 5 段
According to Dennis Ritchie (creator of C ) and Brian Kernighan , C is not a strongly typed language. Following lines are from the book The C programming language page 3 paragraph 5
C 被认为是静态类型(不能将变量从 int 更改为 float)。 一旦声明了一个变量,它就会陷入这种状态。
但它被认为是弱类型,因为类型可以翻转。
0是什么? '\0'、FALSE、0.0 等。
在许多语言中,您不能说 IF(变量),因为条件只会从布尔表达式中获取布尔值。 这些是更强类型的。 这同样适用于在字符和整数之间进行转换。
基本上,c 有两种主要的简单数据类型:整数和浮点数(尽管精度不同)。 其他所有布尔值、枚举(不简单但合适)等都作为其中之一实现。 甚至字符基本上也是整数。
与其他语言相比,其他语言有字符串类型、只能分配给定义值的枚举类型、只能使用生成布尔值或 true/false 的表达式的布尔类型。
但你可以说,与 Perl 相比,C 是强类型的。 所以它是那些著名的争论之一(vi 与 emacs、linux 与 windows 等)。 C# 的类型比 C 强。基本上你可以争论任何一种方式。 你的答案可能是双向的:) 另外一些教科书/网页会说 C 是弱类型,有些会说 C 是强类型。 如果你去维基百科,C 条目会说“部分弱类型”。 我想说,与 Python 相比,C 是弱类型的。 所以 Python/C#、C、Perl 处于连续体上。
C is considered statically typed (you can't have a variable change from int to float). Once a variable is declared it is stuck that way.
But it is considered weakly typed because the types can be flip flopped.
What is 0? '\0', FALSE, 0.0, etc..
in many languages you can't say IF (variable) because conditions will only take boolean values from boolean expressions. These are more strongly typed. The same applies to going between characters and integers.
basically c has two main simple data types, integers and floating point numbers (though various precisions). Everything else booleans, enums (not simple but it fits), etc. are implemented as one of those. Even characters are basically integers.
Compare to other languages where there are string types, enum types that can only be assigned to the defined values, boolean types where only expressions that generate booleans or true/false can be used.
But you can argue that compared to Perl C is strongly typed. So it is one of those famous arguments (vi vs emacs, linux vs windows, etc.). C# is stronger typed than C. Basically you can argue either way. And your answers will probably go both ways :) Also some textbooks/web pages will say C is weakly typed, and some will say C is strongly typed. If you go to wikipedia the C entry says "partially weak typing". I would say compared to Python C is weakly typed. So Python/C#, C, Perl on the continuum.
这里有很多好的答案。 我想提出现实世界Haskell中的一个重要观点:
(剪断)
因此,请查看有关 C 和 C++ 的答案,但请记住“强”和“弱”并不映射为“好”和“坏”。
Plenty of good answers here. I want to bring up an important point from Real World Haskell:
(snip)
So, look at the answers about C and C++, but remember that 'strong' and 'weak' do not map to 'good' and 'bad'.
在我看来,C/C++ 是强类型的。 由于 C 与机器的接近性,存在允许类型转换的 hacks (void*)。 换句话说,您可以从 Pascal 调用汇编程序命令并操作指针,并且 Pascal 仍然被视为强类型语言。 您可以通过 JNI 从 Java 调用汇编程序和 C 可执行文件,但它不会使 Java 成为弱类型。
C 只是用原始指针等“嵌入”了汇编程序。
In my opinion, C/C++ are strongly typed. The type of hacks that allow types to be converted (void*) are there because of C's closeness to the machine. In other words, you can call assembler commands from Pascal and manipulate pointers and Pascal is still regarded as a strongly typed language. You can call assembler and C executables from Java through JNI but it doesn't make Java weakly typed.
C just has assembler "embedded" in it with raw pointers and such.
术语“强类型”没有达成一致的定义。 因此,除非您定义“强类型”的含义,否则无法回答您的问题。
根据我的经验,“强类型”和“弱类型”这两个术语仅被巨魔使用,因为它们缺乏定义,使得巨魔可以在争论中重新定义它们以适应他们的议程。 除了引发口水战之外,这些术语几乎毫无用处。
您可能还想查看 StackOverflow 上的强类型语言的关键方面是什么?。
The term strongly typed doesn't have a agreed-upon definition. Therefore, unless you define what you mean by "strongly typed", it is impossible to answer your question.
In my experience, the terms "strongly typed" and "weakly typed" are used exclusively by trolls, because their lack of definitions allows the trolls to redefine them mid-argument to suit their agenda. Other than for starting flamewars, these terms are pretty much useless.
You might also want to take a look at What are the key aspects of a strongly typed language? here on StackOverflow.
“弱类型”和“强类型”之间存在一个具有多个并行途径的连续体,这两个术语甚至没有很好的定义。
C 是静态类型的,因为编译器知道每个局部变量和结构成员的声明类型是什么。
如果每个对象都有特定类型但编译器无法知道该类型,则动态类型语言可能仍然是强类型的。
There is a continuum with multiple parallel avenues between "weakly typed" and "strongly typed", two terms which are not even well defined.
C is statically typed, in that the compiler knows what the declared type of every local variable and struct member is.
Dynamically typed languages might still be strongly typed, if each object has a specific type but there is no way for the compiler to know that type.
我想说 C 是强类型的,正如你的编译器/平台所规定的那样。 例如,如果您在严格的平台上进行构建,则取消引用类型双关指针可能会失败:
现在,如果您告诉编译器跳过严格的别名,这将不是问题,但不太可移植。 因此,从这个意义上说,突破语言的界限是可能的,但可能不是最好的主意。 这超出了典型的铸造,即铸造 int 一样长,并且真正显示了 void 可能的陷阱之一。
所以,我想说 C 基本上是严格类型的,但它的各种编译器假定程序员最了解并允许一定的灵活性。 这实际上取决于编译器,有些编译器不会注意到潜在的问题。 因此从这个意义上说,选择的编译器在回答问题时确实发挥了作用。 正确的内容通常与编译器允许您逃脱的内容不同。
I would say that C is as strongly typed as your compiler / platform dictates. For instance, if you are building on a strict platform, dereferencing a type punned pointer is likely going to break:
Now, if you told the compiler to skip strict aliasing, it would be a non issue, but not very portable. So, in that sense, pushing the bounds of the language is possible but probably not the best idea. That goes a step beyond typical casting, i.e. casting int as long and really shows one of the possible pitfalls of void.
So, I would say C is basically strictly typed, but its various compilers presume that the programmer knows best and allows some flexibility. This really depends on the compiler, some would not pick up on that potential oops. So in that sense, the compiler of choice really plays a role when answering the question. What is correct often differs from what your compiler will allow you to get away with.