By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,158 Members | 964 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,158 IT Pros & Developers. It's quick & easy.

Problems with typedef

P: n/a

Hi All,

I'm a bit confused by the following which is causing one of
our user's codes fail in compilation:

typedef struct SctpDest_S;

1) Is this standard ?
2) If so ( or even if not so ! ) what is it supposed to do ?

The error message is

"A typedef declaration must declare a name."

which seems to make sense ! Sorry if I missing the obvious
but it's not related to 1.17 in the FAQ, is it ?

On similar grounds he has typedefs of the form

typedef struct SctpHeartbeatChunk_S
{
SctpChunkHdr_S sHdr;
u_short usInfoType;
u_short usInfoLength;
double dTimestamp;
SctpDest_S *spDest;
};

Again is this standard and what is it supposed to do ? ( though this time
I might be able to guess )

Sorry if this is obvious, looking in K&R2 I can't find it and C is very much
my second language (I'm a Fortran guy),
Ian

Jun 29 '06 #1
Share this Question
Share on Google+
15 Replies


P: n/a
Ian Bush wrote:
I'm a bit confused by the following which is causing one of
our user's codes fail in compilation:

typedef struct SctpDest_S;

1) Is this standard ?
2) If so ( or even if not so ! ) what is it supposed to do ?

The error message is

"A typedef declaration must declare a name."

which seems to make sense ! Sorry if I missing the obvious
but it's not related to 1.17 in the FAQ, is it ?
A typedef creates a new name (I call it a "synonym") for an existing
type, so you need to provide two names, the old and the new.

You are giving only one: SctpDest_S

It should be either

typedef struct SctpDest_S new_name;

or

typedef struct old_name SctpDest_S;
On similar grounds he has typedefs of the form

typedef struct SctpHeartbeatChunk_S
{
SctpChunkHdr_S sHdr;
u_short usInfoType;
u_short usInfoLength;
double dTimestamp;
SctpDest_S *spDest;
};

Again is this standard and what is it supposed to do ? ( though this time
I might be able to guess )

Sorry if this is obvious, looking in K&R2 I can't find it and C is very much
my second language (I'm a Fortran guy),

Jun 29 '06 #2

P: n/a
Roberto Waltman wrote:
Ian Bush wrote:
I'm a bit confused by the following which is causing one of
our user's codes fail in compilation:

typedef struct SctpDest_S;

1) Is this standard ?
2) If so ( or even if not so ! ) what is it supposed to do ?

The error message is

"A typedef declaration must declare a name."

which seems to make sense ! Sorry if I missing the obvious
but it's not related to 1.17 in the FAQ, is it ?


A typedef creates a new name (I call it a "synonym") for an existing
type, so you need to provide two names, the old and the new.

You are giving only one: SctpDest_S

It should be either

typedef struct SctpDest_S new_name;

or

typedef struct old_name SctpDest_S;


Yes, I understand this. However my user has not and I am wondering if under
any circumstances it may mean anything, and if so what are those circumstances
and what does it mean ?

Thanks,

Ian

Jun 29 '06 #3

P: n/a
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Roberto Waltman wrote:
Ian Bush wrote:
I'm a bit confused by the following which is causing one of
our user's codes fail in compilation:

typedef struct SctpDest_S;

1) Is this standard ?
2) If so ( or even if not so ! ) what is it supposed to do ?

The error message is

"A typedef declaration must declare a name."

which seems to make sense ! Sorry if I missing the obvious
but it's not related to 1.17 in the FAQ, is it ?
A typedef creates a new name (I call it a "synonym") for an existing
type, so you need to provide two names, the old and the new.


ITYM
"so you need to provide a type and a name".
You are giving only one: SctpDest_S
ITYM
"You are giving only the name"
It should be either

typedef struct SctpDest_S new_name;
which contains a type "struct SctpDest_S" and a name "new_name"
or

typedef struct old_name SctpDest_S;


which contains a type "struct old_name" and a name "SctpDest_S"
On similar grounds he has typedefs of the form

typedef struct SctpHeartbeatChunk_S
{
SctpChunkHdr_S sHdr;
u_short usInfoType;
u_short usInfoLength;
double dTimestamp;
SctpDest_S *spDest;
};
which has a type of "struct SctpHeartbeatChunk_S { ... }" but no name.
Again is this standard and what is it supposed to do ? ( though this time
I might be able to guess )
AFAIK, this isn't standard, and it should not compile. It is an
incomplete typedef, lacking a name to be typedef'ed to the given type.
Sorry if this is obvious, looking in K&R2 I can't find it and C is very much
my second language (I'm a Fortran guy),

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (MingW32) - WinPT 0.11.12

iD8DBQFEo9yTagVFX4UWr64RAqwOAKCuTRe2TSQZHqXbBk23Lv VLR29+ngCfVS4a
WGlbAVDN0yOfTGv3SjRgOrs=
=AL4R
-----END PGP SIGNATURE-----

Jun 29 '06 #4

P: n/a
Ian Bush wrote:
Hi All,

I'm a bit confused by the following which is causing one of
our user's codes fail in compilation:

typedef struct SctpDest_S;

1) Is this standard ?
2) If so ( or even if not so ! ) what is it supposed to do ?

The error message is

"A typedef declaration must declare a name."

which seems to make sense ! Sorry if I missing the obvious
but it's not related to 1.17 in the FAQ, is it ?

On similar grounds he has typedefs of the form

typedef struct SctpHeartbeatChunk_S
{
SctpChunkHdr_S sHdr;
u_short usInfoType;
u_short usInfoLength;
double dTimestamp;
SctpDest_S *spDest;
};

Again is this standard and what is it supposed to do ? ( though this time
I might be able to guess )


typedef requires a type and a name that will become a synonym for that
type. In the first example "struct SctpDest_S" is the type, in the
second example the entire struct definition is the type. In both cases
the name is missing so neither of them are valid C constructs.

Robert Gamble

Jun 29 '06 #5

P: n/a
Ian Bush wrote:
Roberto Waltman wrote:
It should be either
typedef struct SctpDest_S new_name;
or
typedef struct old_name SctpDest_S;
Yes, I understand this. However my user has not and I am wondering if under
any circumstances it may mean anything,


I don't think so. If you didn't read it already, see Lew Pitcher's
corrections to my post.
and if so what are those circumstances
and what does it mean ?


A shot in the dark: If you know that code "worked" somewhere, could it
be that is was produced by a tool, or run through the C preprocessor,
and a missing definition is being substituted by an empty string?
Jun 29 '06 #6

P: n/a


Ian Bush wrote On 06/29/06 11:01,:
Roberto Waltman wrote:

Ian Bush wrote:
I'm a bit confused by the following which is causing one of
our user's codes fail in compilation:

typedef struct SctpDest_S;

1) Is this standard ?
2) If so ( or even if not so ! ) what is it supposed to do ?

The error message is

"A typedef declaration must declare a name."

which seems to make sense ! Sorry if I missing the obvious
but it's not related to 1.17 in the FAQ, is it ?


A typedef creates a new name (I call it a "synonym") for an existing
type, so you need to provide two names, the old and the new.

You are giving only one: SctpDest_S

It should be either

typedef struct SctpDest_S new_name;

or

typedef struct old_name SctpDest_S;

Yes, I understand this. However my user has not and I am wondering if under
any circumstances it may mean anything, and if so what are those circumstances
and what does it mean ?


Others have explained that the declaration is wrong,
but your problem seems to be convincing your user of its
wrongness. Perhaps if you ask him to ponder

typedef int;

.... he'll begin to come around.

--
Er*********@sun.com

Jun 29 '06 #7

P: n/a
Ian Bush wrote:
Hi All,

I'm a bit confused by the following which is causing one of
our user's codes fail in compilation:

typedef struct SctpDest_S;

1) Is this standard ?
2) If so ( or even if not so ! ) what is it supposed to do ?

The error message is

"A typedef declaration must declare a name."

which seems to make sense ! Sorry if I missing the obvious
but it's not related to 1.17 in the FAQ, is it ?

On similar grounds he has typedefs of the form

typedef struct SctpHeartbeatChunk_S
{
SctpChunkHdr_S sHdr;
u_short usInfoType;
u_short usInfoLength;
double dTimestamp;
SctpDest_S *spDest;
};

Again is this standard and what is it supposed to do ? ( though this time
I might be able to guess )

Sorry if this is obvious, looking in K&R2 I can't find it and C is very much
my second language (I'm a Fortran guy),
Ian


Try:

typedef struct SctpHeartbeatChunk_S
{

SctpChunkHdr_S sHdr;
u_short usInfoType;
u_short usInfoLength;
double dTimestamp;
SctpDest_S *spDest;

} SctpHeartbeatChunk_S;
Jun 29 '06 #8

P: n/a
Ian Bush wrote:
Hi All,

I'm a bit confused by the following which is causing one of
our user's codes fail in compilation:

typedef struct SctpDest_S;

(in addition to the other replies)
grep through the code and see if he ever uses SctpDest_S
like this:
SctpDest_S variable_name;

as opposed to this:
struct SctpDest_S variable_name;

If he does, then I'm guessing (which is always a bad idea but
unavoidable sometimes to the maintainer) that he *may* have
meant:
typedef struct SctpDest_S SctpDest_S;

<snipped>

hth
goose

Jun 29 '06 #9

P: n/a
Ian Bush wrote:

Hi All,

I'm a bit confused by the following which is causing one of
our user's codes fail in compilation:

typedef struct SctpDest_S;

1) Is this standard ?
No.
The procedure, or a procedure,
for writing a typedef is
first you write something that looks exactly like
an object definition or a function definition.

int My_def;

Then you write typedef in front of it.

typedef int My_def;
The only way that

struct SctpDest_S;

could be an object definition,
would be if SctpDest_S was some kind of funky macro.
On similar grounds he has typedefs of the form

typedef struct SctpHeartbeatChunk_S
{
SctpChunkHdr_S sHdr;
u_short usInfoType;
u_short usInfoLength;
double dTimestamp;
SctpDest_S *spDest;
};


Same problem.

This way would be OK,
as long as all the member types are defined:

typedef struct {
SctpChunkHdr_S sHdr;
u_short usInfoType;
u_short usInfoLength;
double dTimestamp;
SctpDest_S *spDest;
} SctpHeartbeatChunk_S;

--
pete
Jun 29 '06 #10

P: n/a
In article <Q9Sog.105587$iF6.38583@pd7tw2no>
John Smith <JS****@mail.net> wrote:

[edited down for reply purposes]
typedef struct SctpHeartbeatChunk_S { /* contents */ } SctpHeartbeatChunk_S;


Never do that.

"What, never?"
"No, never!"
"What, never?"
"Well, hardly ever!"
-- Gilbert & Sullivan

:-)

More seriously, this uses a *combination* of *two* separate
constructs:

struct tag { /* contents */ };

and:

typedef existing_type new_name;

The "existing type", in this case, is the one created by:

struct tag { /* contents */ };

and then the typedef is stuck in front of that, and the new_name
behind that, to define a new name -- an alias -- for the existing
type.

This construct apparently confuses many C programmers: they seem
to believe that it is the "typedef" keyword that is creating the
type, rather than the "struct" keyword. (After all, the keyword
itself is "type def(ine)", so obviously it means "define a type",
right? In the same way that "static int f()" means that the function
f() generates static electricity, right? :-) )

My recommendation is to avoid typedef entirely, if possible; but
if you must use it, break the above into three separate pieces.
Start by declaring the existence of the new type:

struct foo;

Then make an alias for the new type:

typedef struct foo Foo;

Finally, fill out the contents of the type:

struct foo {
/* contents */
};

If you do it this way, it will *always* work right, in *every*
situation (including inner scopes within functions). As a bonus,
if you have mutually-referential structures, you can declare them
and their aliases *first*, and then *use* those aliases when
filling out the contents:

struct FileList;
struct DirectoryList;
typedef struct FileList FileList;
typedef struct DirectoryList DirectoryList;

struct FileList {
FileList *nextfile; /* next file in list of files */
DirectoryList *dir; /* directory that contains this file */
... other data ...
};

struct DirectoryList {
DirectoryList *nextdir; /* next dir in list of dirs */
FileList *firstfile; /* first file in this directory */
... other data ...
};

(I prefer to just write out the "struct" keyword and use the tags.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Jun 29 '06 #11

P: n/a
Chris Torek wrote:
My recommendation is to avoid typedef entirely, if possible; but
if you must use it, break the above into three separate pieces.
Start by declaring the existence of the new type:

struct foo;

Then make an alias for the new type:

typedef struct foo Foo;

Finally, fill out the contents of the type:

struct foo {
/* contents */
};

Like this?

#include <stdio.h>
struct mystruct;
typedef struct mystruct starstruct;
struct mystruct {
int a;
int b;
};

int main(void)
{
starstruct foo;
foo.a = 2;
foo.b = 3;

printf("%d %d\n", foo.a, foo.b);

return 0;
} If you do it this way, it will *always* work right, in *every*
situation (including inner scopes within functions).
I will certainly defer to your expertise, but I learned the
former "hybrid" construct from a professional programmer and have
used it in my hobby code for years without a problem. Can you
give an example of it not working right?
(I prefer to just write out the "struct" keyword and use the tags.)


I hate to type. :-)
Jun 29 '06 #12

P: n/a
pete wrote:
The procedure, or a procedure,
for writing a typedef is
first you write something that looks exactly like
an object definition or a function definition.


That should be "declaration", instead of "definition".
/* BEGIN new.c */

typedef void str_squeeze(char *s1, const char *s2);

int main(void)
{
str_squeeze *p = 0;

return p != 0;
}

/* END new.c */
--
pete
Jun 30 '06 #13

P: n/a

Hi All,

Ian Bush wrote:
I'm a bit confused by the following which is causing one of
our user's codes fail in compilation:

typedef struct SctpDest_S;

1) Is this standard ?
2) If so ( or even if not so ! ) what is it supposed to do ?


Thanks everybody for your help (mainly to back me up that this
was the problem, not the compiler). In fact after a longer email
exchange with the user it turned out to be a manifestation of 1.15
in the FAQ.

Thanks again for your help, especially because I learnt something
in sorting out this query,

Ian

Jun 30 '06 #14

P: n/a
Eric Sosman wrote:
typedef struct SctpDest_S;

Others have explained that the declaration is wrong,


The declaration is useless but I'm pretty sure it is not wrong, and
that a compiler that rejects it is broken (unless C99 changed in this
regard). The relevant constraint is 6.7#2:

"A declaration shall declare at least a declarator (other than the
parameters of a function or the members of a structure or union), a
tag, or the members of an enumeration."

typedef struct S; declares a tag, so does not violate this constraint,
and the semantics for typedef don't require any minimum number of
declarators.
but your problem seems to be convincing your user of its
wrongness. Perhaps if you ask him to ponder

typedef int;


typedef int; declares nothing, and so does violate the constraint.

Jun 30 '06 #15

P: n/a
>Chris Torek wrote:
My recommendation is to avoid typedef entirely, if possible; but
if you must use it, break the above into three separate pieces.
Start by declaring the existence of the new type:

struct foo;

Then make an alias for the new type:

typedef struct foo Foo;

Finally, fill out the contents of the type:

struct foo {
/* contents */
};

If you do it this way, it will *always* work right, in *every*
situation (including inner scopes within functions).

In article <urZog.110217$IK3.5117@pd7tw1no>,
John Smith <JS****@mail.net> wrote:... I learned the former "hybrid" construct [i.e., "typedef struct tag { ...} alias;"]from a professional programmer and have
used it in my hobby code for years without a problem. Can you
give an example of it not working right?


Examples are a little tricky, as the worst-case problem occurs
only with what I consider "poor style" in the first place.

Of course, the simplest, most "obvious" problem with:

typedef struct list { /* linked list of key/value pairs */
struct list *next;
int key, value;
} List;

is that we have to write "struct list *next" in the definition
of the structure. If you split it up into:

typedef struct list List;
struct list {
List *next;
int key, value;
};

you get to use your shortcut-name ("List") instead of pressing
the seven keys s t r u c t <spacebar>.

If you have mutually-referential structures, you can use the same
technique, again writing all the "typedef" lines first:

typedef struct S1 S1;
typedef struct S2 S2;
struct S1 {
S1 *next; /* linked list of "S1"s */
S2 *other; /* with a reference to an "S2" */
... data ...
};
struct S2 {
S2 *next; /* linked list of "S2"s */
S1 *other; /* with a reference to an "S1" */
... data ...
};

This works because the first mention of a struct tag, in a scope
in which no such tag is yet visible, defines a new type with that
name -- "struct <whatever>" -- at the current scope. At file scope,
when "struct S1" and "struct S2" are not yet defined, the first
mention occurs inside the combined "typedef struct <tag> <alias>"
line.

If you are, for whatever reason, happy to type out the keyword
"struct" inside the definitions, you can even combine all of the
above into:

typedef struct S1 {
struct S1 *next;
struct S2 *other;
... data ...
} S1;
typedef struct S2 {
struct S2 *next;
S1 *other; /* note: asymmetry */
... data ...
} S2;

Inside a block, however, the picture *can* be different. Consider
the following code:

typedef struct S1 { int x; } S1;
typedef struct S2 { int y; } S2;

void f(void) {
typedef struct S1 {
struct S1 *next;
struct S2 *other;
int s1_member;
} S1;
typedef struct S2 {
struct S2 *next;
S1 *other;
int s2_member;
} S2;

S1 tmp1;
S2 tmp2;

tmp1.other = &tmp2; /* note: this is line 19 */
}

If I feed this code fragment to gcc, I get:

t.c: In function `f':
t.c:19: warning: assignment from incompatible pointer type

Do you see why?

Here, tmp1 is an object of type "struct S1" (or its alias, S1).
It contains a member named "other" which has type "struct S2 *" --
and "tmp2" is an object of type "struct S2" (or its alias S2).
So why can I not set tmp1.other to point to tmp2?

The answer is that these are *different* "struct S2"s. This becomes
a little more obvious if we add one more line (and #include <stdio.h>
as needed):

printf("%d\n", tmp1.other->s2_member);

which produces:

t.c:22: structure has no member named `s2_member'

but if we change that to:

printf("%d\n", tmp1.other->y);

the compiler stops complaining about the printf() line.

To fix this, we have to use a feature added way back in C89,
the "vacuous" structure declaration. Inserting the line:

struct S2;

at the top of f(), before the definition of the new, inner-scope
"struct S1" and its alias, fixes everything:

#include <stdio.h>

typedef struct S1 { int x; } S1;
typedef struct S2 { int y; } S2;

void f(void) {
struct S2;
typedef struct S1 {
struct S1 *next;
struct S2 *other;
int s1_member;
} S1;
typedef struct S2 {
struct S2 *next;
S1 *other;
int s2_member;
} S2;

S1 tmp1;
S2 tmp2;

tmp1.other = &tmp2;
tmp2.s2_member = 42;
printf("%d\n", tmp1.other->s2_member);
}

int main(void) {
f();
return 0;
}
% cc -O -W -Wall -ansi -pedantic -o t t.c
% ./t
42
%

In various specific cases, the vacuous "struct" line can be removed,
but in the general case, writing them all out is always completely
safe.

Note that writing:

typedef struct S1 { int x; } S1;
typedef struct S2 { int y; } S2;

void f(void) {
typedef struct S1 S1;
typedef struct S2 S2;
struct S1 {
S1 *next;
S2 *other;
int s1_member;
};
struct S2 {
S2 *next;
S1 *other;
int s2_member;
};
...
}

does *not* work, because the inner "typedef" lines refer back to
the existing "struct S1" and "struct S2", so that the aliases in
f() still refer to the outer "struct S1" and outer "struct S2".
This is presumably not what the programmer had in mind.

(Note that you have to use the vacuous definition of "struct S2"
even if you avoid the "typedef" keyword, whenever you write code
that shadows identifiers like this. For some reason, it "looks
less odd" to me than the version with the typedefs, though.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Jun 30 '06 #16

This discussion thread is closed

Replies have been disabled for this discussion.