"extern struct foobar" linux compilation warning

R

Rick Anderson

All,

I am receiving the following compilation error on LINUX
(but not Solaris, HPUX, WIN32, etc):

compiling osr.c
LBFO.h(369): warning #64: declaration does not declare anything
extern struct foobar;
^

This is apparently a forward reference to a data structure
for the purposes of declaring a pointer to this opaque
structure.

Any ideas how to get rid of this warning???

Thanks in advance!
Rick
 
K

Kevin Bracey

In message <[email protected]>
Rick Anderson said:
I am receiving the following compilation error on LINUX
(but not Solaris, HPUX, WIN32, etc):

compiling osr.c
LBFO.h(369): warning #64: declaration does not declare anything
extern struct foobar;
^

This is apparently a forward reference to a data structure
for the purposes of declaring a pointer to this opaque
structure.

Any ideas how to get rid of this warning???

Remove the "extern". It's meaningless unless you're actually declaring an
object, which you're not. You're merely naming a structure type.
 
M

Michael Mair

Rick said:
All,

I am receiving the following compilation error on LINUX
(but not Solaris, HPUX, WIN32, etc):

compiling osr.c
LBFO.h(369): warning #64: declaration does not declare anything
extern struct foobar;
^

extern struct foobar baz;

would make sense.

struct foobar;

can make sense.
"extern" goes with objects, not with types.

This is apparently a forward reference to a data structure
for the purposes of declaring a pointer to this opaque
structure.

Is it?

If it is really necessary to get something opaque,
use void *:

typedef void * FooBarHandle;

The user gets only the handle and even a look at the
typedef does not tell how and where information is stored.
If the user can be trusted to not circumvent your access
macros and functions (and your data structures are not
top secret), the header file giving the type definition
for "struct foobar" should be included.
Any ideas how to get rid of this warning???

Heal the code.


Cheers
Michael
 
R

Rick Anderson

BTW: This is the "icc" (intel compiler) *not*
gcc...

It appears -fms_extensions compiler option is not supported.

FYI

Thanks!
Rick
 
K

Kevin Bracey

In message <[email protected]>
Michael Mair said:
If it is really necessary to get something opaque,
use void *:

typedef void * FooBarHandle;

The user gets only the handle and even a look at the
typedef does not tell how and where information is stored.
If the user can be trusted to not circumvent your access
macros and functions (and your data structures are not
top secret), the header file giving the type definition
for "struct foobar" should be included.

I beg to differ. I'd prefer

typedef struct foobar *FooBarHandle;

leaving the contents of struct foobar opaque. That gives you a bit more type
safety - someone can't accidentally give you a BarHandle instead of a
FooBarHandle.
 
M

Michael Mair

Kevin said:
In message <[email protected]>



I beg to differ. I'd prefer

typedef struct foobar *FooBarHandle;

leaving the contents of struct foobar opaque. That gives you a bit more type
safety - someone can't accidentally give you a BarHandle instead of a
FooBarHandle.

You are right, at least for the application at hand.

I was thinking of completely opaque information where you do not
even want the people to know what kind of type may be underlying,
i.e. if the type in question is an array, structure or whatever
-- in this case, one obviously does not want type safety.


Cheers
Michael
 
C

CBFalconer

Kevin said:
I beg to differ. I'd prefer

typedef struct foobar *FooBarHandle;

leaving the contents of struct foobar opaque. That gives you a
bit more type safety - someone can't accidentally give you a
BarHandle instead of a FooBarHandle.

Exactly what I was mulling how to express, when I decided to look
onwards and see what others had said about it. void* allows you to
receive and pass pointers of unknown types and purpose onward
freely, but this is not such a case.
 
I

Ian Pilcher

Kevin said:
I beg to differ. I'd prefer

typedef struct foobar *FooBarHandle;

leaving the contents of struct foobar opaque. That gives you a bit more type
safety - someone can't accidentally give you a BarHandle instead of a
FooBarHandle.

Definitely better than a void *, but really not necessary. As long as

struct foobar;

is declared, pointers to struct foobar can be freely passed around, but
not dereferenced.
 
R

Rick Anderson

Kevin Bracey wrote:
Definitely better than a void *, but really not necessary. As long as

struct foobar;

is declared, pointers to struct foobar can be freely passed around,
but not dereferenced.

That works great - thanks!
Rick
 
K

Kevin Bracey

In message <[email protected]>
Ian Pilcher said:
Definitely better than a void *, but really not necessary. As long as

struct foobar;

is declared, pointers to struct foobar can be freely passed around, but
not dereferenced.

Ah, but making it a typedef hides the fact the handle is a struct from the
basic API. One might want (for whatever reason) to change the handle from an
int to a structure or vice-versa.
 
C

Chris Torek

... [using] a typedef hides the fact the handle is a struct from the
basic API. One might want (for whatever reason) to change the handle
from an int to a structure or vice-versa.

Sure -- but then one could just define a struct containing a single
"int".

Always just use "struct"; it is C's way of defining abstract data
types. :)

I am "only almost kidding" about "always", too. Note that using a
struct to hold a single scalar variable gives you type-safety:

struct temperature { double val; };
struct pressure { double val; };

Now it is impossible to accidentally pass a "temperature" to a
function requiring a "pressure". You can add a typedef if you
really want:

#ifdef USE_TYPEDEFS
typedef struct temperature Temperature;
typedef struct pressure Pressure;
typedef struct counter Counter;
#endif

struct temperature; /* opaque */
struct pressure; /* opaque */
struct counter { int val; }; /* exposed */

If you make the handle an int, you are stuck. If you make it a
typedef and make the typedef an int and someone uses an int, you
are *still* stuck:

/* remove previous typedef and struct */
typedef int Counter;

extern Counter add(Counter previous, int offset);
...
/* bad programmer, using int instead of the typeef-name: */
void f(void) {
int x;
...
x = add(x, 3); /* this code compiles just fine */
...
}

but if you use a struct -- whether opaque or exposed -- even the
bad programmer has to use the name you gave it:

/* put back typedef and struct */

/* bad programmer attempts to use int instead of the typedef-name: */
void f(void) {
int x;
...
x = add(x, 3); /* error: function add() requires a
struct counter and returns a struct counter,
so this code does not compile */
...
}

Of course, if you always use struct, the typedef is unnecessary. Just
think of the word "struct" as meaning "type":

#define type struct

type foo; /* declare type foo to exist */
type bar; /* declare type bar to exist */

static type foo x = FOO_INITIALIZER; /* make x a foo */
extern type bar y; /* declare y as a bar, defined elsewhere */

and you have a language with an obvious user-defined abstract data
type mechanism. Take out the single "#define" and you still have
that language -- it is called "C". :) (Of course, to get everything
to work right, you need C99 with its compound-literals.)
 

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

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top