C 是强类型的吗?

引用 维基百科的话:

两种常用的语言 支持多种隐含的 转换是 C 和 C + + ,它是 有时声称这些是 弱类型语言。然而, 其他人则认为这些语言 对如何做做足够的限制 不同类型的操作数可以是 混杂在一起,两者应被视为 作为强类型语言。

还有更明确的答案吗?

59108 次浏览

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.

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?

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 of void*. void* can also be converted to a pointer to any type without a cast (only in C, not in C++), which is another weakness.

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.

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).

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.

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.

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.

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.

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.

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:

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


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

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.

"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.

Not strongly typed.

Consider what the following function prototype tells you about the data types of the arguments:

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

Nothing. So I suggest that strong typing does not apply here.

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.

Plenty of good answers here. I want to bring up an important point from Real World Haskell:

It is useful to be aware that many language communities have their own definitions of a “strong type”. Nevertheless, we will speak briefly and in broad terms about the notion of strength in type systems.

(snip)

The fireworks around type systems have their roots in ordinary English, where people attach notions of value to the words “weak” and “strong”: we usually think of strength as better than weakness. Many more programmers speak plain English than academic jargon, and quite often academics really are throwing brickbats at whatever type system doesn't suit their fancy. The result is often that popular Internet pastime, a flame war.

So, look at the answers about C and C++, but remember that 'strong' and 'weak' do not map to 'good' and 'bad'.

c is weakly typed, b is typeless.

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 is not a strongly-typed language, but as it has evolved, its type checking has been strengthened.