If you could change the C or C++ or Java syntax, what would you like different?

J

Jon

Keith said:
Yes. The type doesn't exist before, or in the absence of, the
declaration. It does exist after, or in the presence of, the
declaration.

The programmer can declare a type, but only a compiler can create one.
The declaration is the specification used by the compiler. The programmer
can then later "define" (specify to the compiler to create an instance
of ) a type. (I don't like using "define" this C way, FWIW).

// foo.h
struct foo { int x; }; // type declaration

// foo.c
foo foo_instance; // type "defintion" (actually, type instantiation)
For example, if I write:
struct foo { int x; };
then the type "struct foo" exists.

Not really. It's just declared.
If I don't, it doesn't.
The declaration creates the type.

Not really. That's probably why it's called type declaration and not type
creation. "Introduces" a new name may work.

(That goes without saying).
Yes, except that I fail to see what the word "technically" adds to it.


Ok, so the *intent* of a typedef is to create something that can be
treated as a distinct type, even if the compiler doesn't enforce the
distinction. And if, given the above declarations, I write:

length len = 10;
volume vol = 20;
int z = len + vol;

then my program is logically incorrect, even though there is no error
that a compiler is going to complain about.

If that was Felix Palmen's point, then I agree (and it would have
been nice if he'd simply said so, or at least answered my direct
questions, rather than plonking me.)

My point is simply that that's not what "typedef" really means *in the
language*. And if you want to create a new type and have the compiler
enforce it for you, typedef won't do the job (but a struct will).

And enum and union will also.
 
J

Joshua Maurice

No, it's from the non-compiler-developer/non-language-implementer
perspective.

There is only one perspective: what the language standard says. The
language standard says that a typedef does not define a new type,
typedef never defines types, and so typedef is a misnomer. typedef
defines and/or declares type /names/, but it does not define /types/.
A boy name Sue. Do you *really* think that Sue's dad meant to *define*
the boy or just give him a name? (Bad analogy because dad did influence
(define?) Sue's behavior whereas 'typedef' does nothing of the sort... oh
well).

This is not the real world. Your definitions of the real world are
inapplicable. All that matters is how the language standard defines
the terms. Please reread:
http://www.parashift.com/c++-faq-lite/proper-inheritance.html#faq-21.11
possibly including the sections before it to get a sense of its
context.
 
J

Joshua Maurice

I don't think that is necessarily true at the compiler level, though. Did
you mean at the compiler level?

It is true because that's what the language standard says, so it's
true at the compiler level, source code level, and any other relevant
"level".
 
J

Joshua Maurice

The programmer can declare a type, but only a compiler can create one.
The declaration is the specification used by the compiler. The programmer
can then later "define" (specify to the compiler to create an instance
of ) a type. (I don't like using "define" this C way, FWIW).

// foo.h
struct foo { int x; }; // type declaration

No. That is the definition of a type - it tells the compiler its
members names, types, and layout. It's also a type declaration - it
associates a name with a type.
// foo.c
foo foo_instance; // type "defintion" (actually, type instantiation)

This is neither a type declaration nor type definition. It is a
variable definition - it associates memory for a variable. It's also a
variable declaration - it associates a name with a variable.
 
S

Seebs

It turns out the standard does define the word "definition" (I should
have checked that earlier). C99 6.7p5:

Ack! I didn't even think to check.
A declaration specifies the interpretation and attributes of a set
of identifiers. A definition of an identifier is a declaration for
that identifier that:
-- for an object, causes storage to be reserved for that object;
-- for a function, includes the function body;
-- for an enumeration constant or typedef name, is the (only)
declaration of the identifier.
Huh!

Which isn't quite as coherent as I'd like. I'd rather be able
to say that a definition is a declaration that creates the entity
it declares. Or at least I'd like *some* term for a declaration
that actually creates something (like a function definition), as
opposed to just asserting that something exists (like a function
definition, or "extern int x;", or "struct foo;"). But there it is.

Actually, that's a really interesting way of looking at it.

Consider that, in fact, typedef names and enumeration constants are both
"created" by their declarations. So that's actually consistent; what's
created is the *name*, not the *type*.

But since the name is a name for a type...
So a typedef declaration is a definition. What does it define?
I'd say it defines, not a type, but a new name for a type, but I'm
getting tired of arguing about that. :cool:}

Well, they clearly say "typedef names". So it defines a special thing
called a typedef name, which it turns out is a name which refers to some
specific type.
Hmm. I don't think of it that way. "int" and "struct foo" are
type names. When I say "int is a type", the word int refers to
the type, not to the name. (BTW, types are discussed in 6.2.5,
and type names in 6.7.6.)

Ah-hah. Okay, that makes sense. I have two separate models for what "type"
can mean, and I switch between them; I guess one of them is formally
called a type name.
Did we ever figure out how many angels can dance on the head of
a pin?

It depends on whether they're moshing.

-s
 
K

Keith Thompson

Indeed. I'm used to people with the ability to separate different levels
of abstraction (like, e.g. the modelling layers M0-M3 in UML).
Obviously, there are quite a few people without that ability.

What matters to the programmer does not at all need to exactly match
what matters to the compiler. When programming C, I like defining my
reference types (and also my enumeration types) using 'typedef' and I'm
doing nothing wrong at all.

First off, what do you mean by "reference types"? If you mean
pointer types, hiding pointer types behind typedefs is widely
considered to be a bad idea, unless you want to make the type opaque
(meaning that code that uses the type shouldn't care that it's a
pointer type).

I certainly understand the idea of different levels of abstraction.
The point is, I can pay attention to more than one of them.
You seem to be insisting that the level at which typedef creates
a new logical type (a point which which I've agreed) is the only
one that matters, and that the fact that it doesn't create a new
type at the language level can be ignored. I believe this is a
potentially dangerous attitude.

(I suppose Felix won't see this unless somebody quotes it in
a followup.)
 
K

Keith Thompson

Seebs said:
Consider the declaration:
foo x;
In this declaration, "foo" is a type. Only it's not a type, because there
is no type "foo".

If there's no type named "foo", then "foo x;" is a syntax error.
We can't assume it's a type name; it could be a function name,
and the author forgot the parentheses.
But wait!
typedef int x;
foo x;
Now, "foo" is a type. It has somehow come into being, as though it had
just been defined.

int is a type, "int" and "foo" are names for that type.

I think if you follow the language syntax, you'll find that in "foo x;",
the identifier "foo" resolves to "type-name". (I say "I think" because
I haven't bothered to trace it myself.)
What "typedef" does is define things that you can use wherever you could
otherwise use a type.

It defines names that you can use wherever you can use a type name.
 
S

Seebs

The point is, I can pay attention to more than one of them.
You seem to be insisting that the level at which typedef creates
a new logical type (a point which which I've agreed) is the only
one that matters, and that the fact that it doesn't create a new
type at the language level can be ignored. I believe this is a
potentially dangerous attitude.

I'm curious as to why.

Hmm. Here's the thing. I don't tend to think of types as being "created"
at all. I just think types are described. When I write
struct foo { int x, y; };
I don't really care whether a type is "created" or not; I just care whether
I can now use "struct foo" to refer to things that have two int members, x
and y. I wouldn't even have thought to ask whether a type was "created".

Consider the use of opaque types:
struct foo;
typedef struct foo *foo_t;

After this, have I actually created a type, in your terms? I don't think so,
since I never completed "struct foo", and typedef doesn't do anything. But
from my point of view, I've now created a type "foo_t" which I can use as
an opaque handle for Something Unknown.

-s
 
S

Seebs

If there's no type named "foo", then "foo x;" is a syntax error.
We can't assume it's a type name; it could be a function name,
and the author forgot the parentheses.

Well, yes, but if we're told it's a declaration, that thing is a type-name.
I think if you follow the language syntax, you'll find that in "foo x;",
the identifier "foo" resolves to "type-name". (I say "I think" because
I haven't bothered to trace it myself.)

I think that's right. But...

If we agree that "Keith" is a programmer-name, then we should agree
that Keith is a programmer.
It defines names that you can use wherever you can use a type name.

Yes. And if you have a name for a thing, it's pretty normal to refer to
use the name to refer to the thing, and to say that <word> is a <thing>, where
<word> is actually the name of a thing. Because names get a free
dereference that doesn't need a special operator for them. It's like
function pointers; you don't have to write
(*foo)();
to call through a function pointer, you can just write
foo();
and the language knows what you mean.

If the string "foo" is a type-name, then foo is a type.

-s
 
K

Keith Thompson

Seebs said:
I'm curious as to why.

Because it makes it too easy to assume that the thing created by the
typedef is distinct from the original type both logically (where it is
distinct), and on the language level (where it isn't).

If I write
typedef double length_type;
typedef double mass_type;
I can't depend on the compiler to detect my error if I try to add a
length to a mass.

It's perfectly reasonable to use typedef to create new "logical
types" (size_t and FILE are good examples from the standard library),
but it's important to understand what's happening on both (or more)
abstraction levels.

[...]
 
K

Keith Thompson

Seebs said:
Well, yes, but if we're told it's a declaration, that thing is a type-name.


I think that's right. But...

If we agree that "Keith" is a programmer-name, then we should agree
that Keith is a programmer.

Sure. But the Keith that's a programmer isn't the one that's the first
word of the sentence "Keith is a programmer". It's the one that's
sitting in a chair with a computer on his lap.

The "foo" in "foo x;" isn't a type. foo is a type. "foo" is its name.

[...]
If the string "foo" is a type-name, then foo is a type.

Yup.
 
J

Joshua Maurice

If the string "foo" is a type-name, then foo is a type.

Yes, but there's one more step which I think you're taking implicitly,
so let me clear it up.

struct foo { int x; };
foo is a type name. The above line is a type definition and a type
declaration.

struct bar;
bar is a type name. The above line is a type declaration. It is not a
type definition.

typedef struct foo foo2;
foo2 is a type name. It refers to a type.

We normally say "foo" is a type, and we can also say that "foo2" is a
type. It's a certain loose use of the terms involved, but it's
generally accepted and generally is not error prone, ambiguous, or
confusing. Formally "foo" and "foo2" are not types but are type
names.

"struct foo { int x; };" introduces a new type name. Formally it
declares a type name.

"typedef struct foo foo2;" introduces a new type name. Formally it
declares a type name.

However, unlike "struct foo { int x; };" which defines a (new) type,
"typedef struct foo foo2;" does not define a type. Both declare type
names, but only one defines a type.
 
S

Seebs

Because it makes it too easy to assume that the thing created by the
typedef is distinct from the original type both logically (where it is
distinct), and on the language level (where it isn't).

Ahh!

I guess I wouldn't expect C to catch that kind of thing anyway. I don't
even expect C compilers to tell me when I mismatch genuinely different
types, many cases.
It's perfectly reasonable to use typedef to create new "logical
types" (size_t and FILE are good examples from the standard library),
but it's important to understand what's happening on both (or more)
abstraction levels.

I see. Yeah, I think that's true, but I guess, it would never have
occurred to me to expect typedef to create a type which could be told
apart (except perhaps by an enthusiastic compiler) from a compatible
type, because that's not how I expect C to work. So that's a solution
to a problem I've not seen.

-s
 
S

Seebs

However, unlike "struct foo { int x; };" which defines a (new) type,
"typedef struct foo foo2;" does not define a type. Both declare type
names, but only one defines a type.

But one defines a type-name, and as you've noticed, it's not really
confusing to people to refer to a type-name as a type. :)

-s
 
J

Joshua Maurice

But one defines a type-name, and as you've noticed, it's not really
confusing to people to refer to a type-name as a type.  :)

Except in this case where the distinction is crucial.

Also, C standard technically, you don't "define" names, you "declare"
names. You "define" objects, function, variables, types, and so on.
 
S

Seebs

Except in this case where the distinction is crucial.

Apart from the question of "whether or not someone wins an argument
on the internet", how does the distinction even matter at all?
Also, C standard technically, you don't "define" names, you "declare"
names. You "define" objects, function, variables, types, and so on.

Well, actually, as Keith pointed out, you "define" typedef names. That's
the language the standard uses.

-s
 
J

Joshua Maurice

Apart from the question of "whether or not someone wins an argument
on the internet", how does the distinction even matter at all?

You talk as though arguing fine points on the internet lacks value.
Why do you post if you think that is true? Because it's pedantic, or
because of the venue, does not make it less of an important issue. The
purpose of gathering here is to discuss technical points and learn
from this discussion.
Well, actually, as Keith pointed out, you "define" typedef names.  That's
the language the standard uses.

Could you quote please? Sadly, I do not have a C standard copy handy.
From what I can read from the C++03 standard, it never refers to
defining a name.

C++03, 7.1.3 The typedef specifier / 1
Declarations containing the decl-specifier typedef declare identifiers
that can be used later for naming fundamental (3.9.1) or compound
(3.9.2) types.

I would assume that C is the same in this regard. You declare names,
you define objects, functions, types, etc.
 
F

Felix Palmen

* Vincenzo Mercuri said:
First off, what do you mean by "reference types"? If you mean
pointer types, hiding pointer types behind typedefs is widely
considered to be a bad idea, unless you want to make the type opaque
(meaning that code that uses the type shouldn't care that it's a
pointer type).

That's exactly what is commonly referred to as a "reference type". Its
typical use is in OOP.
I certainly understand the idea of different levels of abstraction.
The point is, I can pay attention to more than one of them.
You seem to be insisting that the level at which typedef creates
a new logical type (a point which which I've agreed) is the only
one that matters, and that the fact that it doesn't create a new
type at the language level can be ignored.

It is the only level that matters for the naming of keywords. They
should be named after what is accomplished in the programmer's view.
I believe this is a
potentially dangerous attitude.
Bullshit.

(I suppose Felix won't see this unless somebody quotes it in
a followup.)

Please stop posting the crap, it's always the same.
 
S

Seebs

You talk as though arguing fine points on the internet lacks value.

No.

I merely talk as though I don't think that distinction is, in fact,
crucial, or significant. I don't think it actually changes anything
about how we program, or the meaning of any valid C program, or
anything else.
Could you quote please? Sadly, I do not have a C standard copy handy.
From what I can read from the C++03 standard, it never refers to
defining a name.
I would assume that C is the same in this regard. You declare names,
you define objects, functions, types, etc.

Nope.

First, let us look at the introduction of typedef, in section 6.7,
"Type Definitions".

In a declaration whose storage-class specifier is typedef,
each declarator defines an identifier to be a typedef name
that denotes the type specified for the identifier in the
way described in 6.7.5.

So, these are "Type Definitions" (that's the heading), and what they
do is *define* an identifier to be a typedef name. More generally,
what is a "definition" in C?

6.7, Declarations, says:

Semantics
5 A declaration specifies the interpretation and attributes of a
set of identifiers. A definition of an identifier is a declaration
for that identifier that:
- for an object, causes storage to be reserved for that object;
- for a function, includes the function body
- for an enumeration constant or typedef name, is the (only)
declaration of the identifier.

So a typedef name does, in fact, have a "definition". That definition
is described in detail under the heading "Type Definitions".

I think, given that the language standard refers to them as "type
definitions", it is not *entirely* beyond the bounds of reason for someone
to suggest that, in some way, they "define types".

-s
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,099
Messages
2,570,626
Members
47,237
Latest member
David123

Latest Threads

Top