What causes you to believe that this is what "define a type" means, or what
"new" means?
This clearly contradicts multiple examples of how the C standard uses
the term. Maybe it's what you think they should have meant, but it's quite
simply not what the standard actually says.
Ok. Pedantic mode.
Claim 1- I claim that the C standard never defines "to define a
type".
Claim 2- I further claim that the only sensible meaning of the phrase
"to define a type" is to introduce or create a new, previously un-
created type, which is distinct from all other types with regards to
the type system.
----
First claim, that the C standard never defines "to define a type".
I'm referencing ISO/IEC 9899:TC3. A copy can be found at the link:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
The term "definition" has a particular meaning in C. All C-definitions
are C-declarations. C-declarations declare C-identifiers. A C-
definition is a property or quality of a C-declaration and of the
associated C-identifier. (See 6.2.1 Scope of Identifiers / 1, 6.2.1
Scope of Identifiers / 4, 6.7 Declarations / 5.)
In particular, a typedef name is declared and defined by a "typedef
statement". (See 6.2.1 Scope of Identifiers / 4, 6.7 Declarations / 5,
6.7.7 Type definitions / 3.)
A typedef name is distinct from the thing to which it refers. (See
6.2.1 Scope of Identifiers / 6.) The standard adopts a loose use of
terminology and uses the name as equivalent to the named thing, but it
says that sometimes the difference is important and it will be
explicitly called out.
The C language standard does not define or use the term "define a
type" explicitly. Instead uses the term "type specifier". (See: 6.2.1
Scope of Identifiers / 4, 6.2.7 Compatible type and composite type /
1.)
One aside:
struct { int x; };
is illegal C code AFAIK. One might say that it defines a type if it
were legal, but there's a strict requirement in the C standard that
all definitions are declarations, and no identifier is declared, so it
is illegal. Of fun note is that we can "fix it" by various means:
Declare and define a variable.
struct { int x; } y;
Declare and define a struct tag.
struct foo { int x; };
Declare and define a typedef name.
typedef struct { int x; } foo;
Note that each of the above is a declaration and a definition
according to the rules of the C standard. Note specifically that we
can "fix" the code "struct { int x; };" by declaring /an object/ or by
declaring /an identifier related to types/ - a struct tag or a typedef
name. Please see that this means that the C standard never talks about
defining types, merely defining type names. There is no well defined
thing called a "type definition" in the C standard, despite the
section in the C standard with that name.
----
Second claim, that the only sensible meaning of the phrase "to define
a type" is to introduce or create a new, previously un-created type,
which is distinct from all other types with regards to the type
system.
Let me work through these questions, and hopefully we can come to some
understanding.
At the very least, types can be "compatible" and they can be not
"compatible", aka "distinct". The words "distinct" and "compatible"
when applied to types refers to how it interacts in the type system. I
think that wiki phrases it quite well:
http://en.wikipedia.org/wiki/Type_system
In computer science, a type system may be defined as "a tractable syntactic framework for classifying phrases according to the kinds of values they compute".[1] A type system associates types with each computed value. By examining the flow of these values, a type system attempts to prove that no type errors can occur. The type system in question determines what constitutes a type error, but a type system generally seeks to guarantee that operations expecting a certain kind of value are not used with values for which that operation makes no sense.
In a type system, there are things called "type errors" when one tries
to do an operation on "values" which "makes no sense". In the C word,
simple assignment is such an operation. For the simple assignment "a =
b;", this will produce a type error when the types of the "values" are
such that the simple assignment "makes no sense". C formalizes this to
mean that the types must be "compatible" or that there exists a (type)
conversion of the right hand side to a type which is "compatible" with
the left hand side.
So, there are types which are "compatible" and there are types which
are "not compatible". One can use the compiler to check by seeing if
we can get "type errors".
Moreover, "compatible" is a binary relation on the set of types.
Obviously it must be an equivalence relation.
I suspect for most programming languages, this "compatible"
equivalence relation is a trivial reflexive relation - a relation
where two elements are "compatible" iff they are the same element. At
the very least, it is a trivial reflexive relation in C. "Two types
have compatible type if their types are the same" (6.2.7 Compatible
type and composite type).
So, two types are compatible
iff they're the same type
iff the type checker of the type system says that they're compatible.
The final question is simple. Can you "define" a specific type more
than once in a specific translation unit? Not the type name aka
identifier, but the actual type.
I see these as the available options:
Option 1- typedef defines a new type.
This is patently false. Let's consider:
struct foo { int x; };
typedef struct foo bar;
int main()
{
struct foo * x;
bar * y = x;
}
We can look over the implicit conversion rules and the constraints in
the C standard, and we can conclude that the type of " * x" and " * y
" must be "compatible" (technical term in the C standard) for this to
compile. (See: ISO/IEC 9899:TC3 - 6.5.16.1 Simple assignment / 6.) We
can then conclude that the types are the same type from the previous
discussion. Thus typedef does not define new types.
Finally, also from the C standard. "A typedef declaration does not
introduce a new type, only a synonym for the type so specified." -
"ISO/IEC 9899:TC3 - Type definitions / 3". A typedef does not
introduce a type. It introduces a synonym for a type. Under any sane
definition of "define a type", typedef does not.
Option 2- typedef defines a type, but that type is already defined.
typedef defines the type /again/. One might say it "redefines" it.
This very much goes against the meaning of the word "define" and
"definition".
An English word in a dictionary can have more than one meaning.
Commonly it is said that the word has more than one definition.
However, this is in a different sense that "defining a type". The
entry in the dictionary itself can be thought of as a singular
definition, made at one instant, inseparatable. It merely has several
meanings based on context, usage, and even then perhaps is ambiguous.
The key is that even English words in a dictionary are only "defined
once". You won't see an entry for a word, then on the next page see
another entry for the same word. In that sense, "definition" is a
singular event. In this sense, the word is defined, and another entry
wouldn't be "define the word again" - it would "redefine" the word.
Also, words can have different definitions based on context. "Metal"
in astrophysics refers to all elements besides Hydrogen and Helium,
but "metal" in chemistry refers only to the transition metals in the
"middle" of the periodic table. In our case, we're restricting our
context to the C programming language, or maybe all programming
languages. As such, we don't have this crossover of terms from
different domains.
I claim that a programming language is similar to the English
dictionary with regards to our problem. A declaration of a program
unambiguously gives meaning to the identifier for its scope. There is
no way to redefine the meaning an identifier in its scope. It's
meaning is set on first use. This is very much like the English
dictionary; each entry as a singular event gives meaning to the word
being defined. To say "define a type which already exists" simply goes
against how the words are commonly used in programming circles.
Any sensible way you look at it, in the programming world you never
define something which has already been defined. As an example, C++
calls this the One Definition Rule - each thing must have at most one
definition (per translation unit), and C++ very clearly spells out the
typedef is not a definition of a type.
In fact, the definition of "definition" in the C standard carries the
same connotation of "singular". (See ISO/IEC 9899:TC3 - 6.7
Declarations / 5.) Each definition of a particular object, function,
enumeration constant, and typedef name, can only happen once (per
translation unit). There is no defining the same thing multiple times.
It would be nonsensical to say you can define a specific type more
than once (in a single translation unit).
Finally, also from the C standard. "A typedef declaration does not
introduce a new type, only a synonym for the type so specified." -
"ISO/IEC 9899:TC3 - Type definitions / 3". A typedef does not
introduce a type. It introduces a synonym for a type. Under any sane
definition of "define a type", typedef does not.
That leaves us with:
Option 3- typedef does not define types.
----
To sum this all up, I have yet to see any contradictory usage of the
terms from reliable text, such as a programming language definition, a
paper written by a programming language expert, etc. Also, I have
found evidence from other programming language communities which
agrees with me (C++ standard). Finally, I have shown that this is the
only sensible definition of "to define a type" which is consistent
with the C standard.