473,796 Members | 2,558 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

incorrect warning?

When I compile the program below "Program start" with
gcc -std=c99 -pedantic -o bgcc bgcc.c
(where gcc --version gives
gcc (GCC) 3.4.5 20051201 (Red Hat 3.4.5-2)
Copyright (C) 2004 Free Software Foundation, Inc.
)
I get the warning
bgcc.c:3: warning: "struct thingTag" declared inside parameter list
bgcc.c:3: warning: its scope is only this definition or declaration, which
is probably not what you want

Should the code generate a warning? Is there a way to avoid it other than
adding
typedef struct thingTag * thingP;
and replacing line 3 with
typedef void (*show)( thingP);
(which does shut gcc up)?

TIA
Duncan

Program start
#include <stdio.h>

typedef void (*show)( struct thingTag *);

typedef struct thingTag
{ show f;
double v;
} thing;

void show_metres( thing* p)
{ printf( "%f m\n", p->v);
}

int main( int argc, char** argv)
{
thing T;
T.v = 1.7;
T.f = show_metres;
T.f( &T);
return 1;
}
Jun 20 '06 #1
10 2107
Why not just do this:

#include <stdio.h>

typedef struct thingTag thing;

typedef void (*show)( thing *);

struct thingTag
{ show f;
double v;

};

void show_metres( thing* p)
{ printf( "%f m\n", p->v);

}

int main( int argc, char** argv)
{
thing T;
T.v = 1.7;
T.f = show_metres;
T.f( &T);
return 1;
}

Jun 20 '06 #2
Duncan Muirhead said:

<snip>
Should the code generate a warning?
<snip>
Program start
#include <stdio.h>
Add a forward declaration here:

struct thingTag;
typedef void (*show)( struct thingTag *);

typedef struct thingTag
{show f;
double v;
} thing;


That should shut it up.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jun 20 '06 #3
Duncan Muirhead <no***@this.add ress> writes:
When I compile the program below "Program start" with
gcc -std=c99 -pedantic -o bgcc bgcc.c
(where gcc --version gives
gcc (GCC) 3.4.5 20051201 (Red Hat 3.4.5-2)
Copyright (C) 2004 Free Software Foundation, Inc.
)
I get the warning
bgcc.c:3: warning: "struct thingTag" declared inside parameter list
bgcc.c:3: warning: its scope is only this definition or declaration, which
is probably not what you want

Should the code generate a warning? Is there a way to avoid it other than
adding
typedef struct thingTag * thingP;
and replacing line 3 with
typedef void (*show)( thingP);
(which does shut gcc up)?

TIA
Duncan

Program start
#include <stdio.h>
/* HERE */
typedef void (*show)( struct thingTag *);
At this point, the compiler hasn't seen "struct thingTag". It doesn't
know that you're going to declare it later.

You can add an incomplete type declaration before the typedef, at the
point marked /* HERE */ above:

struct thingTag;
typedef struct thingTag
{ show f;
double v;
} thing;

void show_metres( thing* p)
{ printf( "%f m\n", p->v);
}

int main( int argc, char** argv)
{
thing T;
T.v = 1.7;
T.f = show_metres;
T.f( &T);
return 1;
Why are you returning 1 from your main program? The only portably
defined results are 0, EXIT_SUCCESS, and EXIT_FAILURE. On many
systems (but not all), "return 1;" from main() indicates a failure.
}


Incidentally, there's no real benefit in creating a typedef for a
structure type. It merely creates an alias "thing" for something that
already has a perfectly good name, "struct thingTag" -- and its an
alias that can't be used as flexibly as the original name.

Here's how I'd probably write it:
=============== =============== ==========
#include <stdio.h>

struct thing;

typedef void (*show)( struct thing *);

struct thing {
show f;
double v;
};

void show_metres(str uct thing* p)
{
printf("%f m\n", p->v);
}

int main(int argc, char** argv)
{
struct thing T;
T.v = 1.7;
T.f = show_metres;
T.f( &T);
return 0;
}
=============== =============== ==========

Though I might be tempted to drop the other typedef as well and write
it like this:
=============== =============== ==========
#include <stdio.h>

struct thing {
void (*f)(struct thing *);
double v;
};

void show_metres(str uct thing* p)
{
printf("%f m\n", p->v);
}

int main(int argc, char** argv)
{
struct thing T;
T.v = 1.7;
T.f = show_metres;
T.f( &T);
return 0;
}
=============== =============== ==========

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jun 20 '06 #4
Duncan Muirhead wrote:
When I compile the program below "Program start" with
gcc -std=c99 -pedantic -o bgcc bgcc.c
(where gcc --version gives
gcc (GCC) 3.4.5 20051201 (Red Hat 3.4.5-2)
Copyright (C) 2004 Free Software Foundation, Inc.
)
I get the warning
bgcc.c:3: warning: "struct thingTag" declared inside parameter list
bgcc.c:3: warning: its scope is only this definition or declaration, which
is probably not what you want

Should the code generate a warning?
The code is invalid and a diagnostic is required. The warning you
quoted is not required, but tells you exactly what you're doing wrong.
Is there a way to avoid it other than adding
typedef struct thingTag * thingP;
and replacing line 3 with
typedef void (*show)( thingP);
(which does shut gcc up)?
Any way you fix it, you'll have to declare struct thingTag once before
you reference it in show's parameter list. It can be as simple as a
"struct thingTag;" on line 2.
#include <stdio.h>

typedef void (*show)( struct thingTag *);
Here you declare one struct thingTag (let's call it struct A), but its
declaration is only the scope of show's parameter list, which is not
what you want. Your compiler gave a very helpful error message, but you
decided to ignore it. Why?
typedef struct thingTag
Since the original struct thingTag went out of scope, here you declare
(and define) a completely different struct thingTag. Let's call it
struct B.
{ show f;
This is still a pointer to a function taking struct A.
double v;
} thing;

void show_metres( thing* p)
{ printf( "%f m\n", p->v);
}

int main( int argc, char** argv)
{
thing T;
T.v = 1.7;
T.f = show_metres;
This line requires a diagnostic. show_metres is a function taking a
pointer to struct B, and T.f requires a pointer to a function taking
struct A. They are different, and there is no implicit conversion
between them in standard C.
T.f( &T);
This line requires a diagnostic. T.f is a pointer to a function taking
a pointer to struct A, and you pass it a pointer to struct B. They are
different, and there is no implicit conversion between them in standard
C.
return 1;
This may exit successfully on some implementations , unsuccessfully on
others, and perhaps even something in-between on yet more. Are you sure
you don't mean EXIT_FAILURE, or 0 or EXIT_SUCCESS ?
}


Jun 20 '06 #5
In article <pa************ *************** *@this.address>
Duncan Muirhead <no***@this.add ress> wrote:
I get the warning
bgcc.c:3: warning: "struct thingTag" declared inside parameter list
bgcc.c:3: warning: its scope is only this definition or declaration, which
is probably not what you want


See <http://groups.google.c om/gr************* *******@news2.n ewsguy.com>.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.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 20 '06 #6
On Tue, 20 Jun 2006 17:57:04 +0000, Keith Thompson wrote:
Duncan Muirhead <no***@this.add ress> writes:
When I compile the program below "Program start" with
gcc -std=c99 -pedantic -o bgcc bgcc.c
(where gcc --version gives
gcc (GCC) 3.4.5 20051201 (Red Hat 3.4.5-2)
Copyright (C) 2004 Free Software Foundation, Inc.
)
I get the warning
bgcc.c:3: warning: "struct thingTag" declared inside parameter list
bgcc.c:3: warning: its scope is only this definition or declaration, which
is probably not what you want

Should the code generate a warning? Is there a way to avoid it other than
adding
typedef struct thingTag * thingP;
and replacing line 3 with
typedef void (*show)( thingP);
(which does shut gcc up)?

TIA
Duncan

Program start
#include <stdio.h>


/* HERE */
typedef void (*show)( struct thingTag *);


At this point, the compiler hasn't seen "struct thingTag". It doesn't
know that you're going to declare it later.

You can add an incomplete type declaration before the typedef, at the
point marked /* HERE */ above:

struct thingTag;
typedef struct thingTag
{ show f;
double v;
} thing;

void show_metres( thing* p)
{ printf( "%f m\n", p->v);
}

int main( int argc, char** argv)
{
thing T;
T.v = 1.7;
T.f = show_metres;
T.f( &T);
return 1;


Why are you returning 1 from your main program? The only portably
defined results are 0, EXIT_SUCCESS, and EXIT_FAILURE. On many
systems (but not all), "return 1;" from main() indicates a failure.
}


Incidentally, there's no real benefit in creating a typedef for a
structure type. It merely creates an alias "thing" for something that
already has a perfectly good name, "struct thingTag" -- and its an
alias that can't be used as flexibly as the original name.

Here's how I'd probably write it:
=============== =============== ==========
#include <stdio.h>

struct thing;

typedef void (*show)( struct thing *);

struct thing {
show f;
double v;
};

void show_metres(str uct thing* p)
{
printf("%f m\n", p->v);
}

int main(int argc, char** argv)
{
struct thing T;
T.v = 1.7;
T.f = show_metres;
T.f( &T);
return 0;
}
=============== =============== ==========

Though I might be tempted to drop the other typedef as well and write
it like this:
=============== =============== ==========
#include <stdio.h>

struct thing {
void (*f)(struct thing *);
double v;
};

void show_metres(str uct thing* p)
{
printf("%f m\n", p->v);
}

int main(int argc, char** argv)
{
struct thing T;
T.v = 1.7;
T.f = show_metres;
T.f( &T);
return 0;
}
=============== =============== ==========


Thank you, all, for your replies. However I am still somewhat bemused.
If I alter the program by adding
typedef struct
{ struct thingTag* p;
} entity;
before the typedef for show, no warnings are generated. If I add it after
show, show (but not entity) generates warnings. Is this difference in
references to undeclared types in functions and structs an oddity of the
language or the compiler?
TIA
Duncan
Jun 21 '06 #7
Duncan Muirhead <no***@this.add ress> writes:
[...]
Thank you, all, for your replies. However I am still somewhat bemused.
If I alter the program by adding
typedef struct
{ struct thingTag* p;
} entity;
before the typedef for show, no warnings are generated. If I add it after
show, show (but not entity) generates warnings. Is this difference in
references to undeclared types in functions and structs an oddity of the
language or the compiler?


Please trim quoted material when you post a followup. Provide enough
context so we can understand what's going on; that seldom requires
quoting everything.

Here's the original (incorrect) program:
=============== =============== ==========
#include <stdio.h>

typedef void (*show)( struct thingTag *);

typedef struct thingTag
{ show f;
double v;
} thing;

void show_metres( thing* p)
{ printf( "%f m\n", p->v);
}

int main( int argc, char** argv)
{
thing T;
T.v = 1.7;
T.f = show_metres;
T.f( &T);
return 1;
}
=============== =============== ==========

The first occurrence of "struct thingTag" is inside the typedef for
"show". Since there's been no complete declaration of that type, the
compiler treats it as an implicit declaration of a new incomplete
type; normally, such an incomplete type would be completed later. But
in this case, the new incomplete type appears within a function
prototype, and its scope is limited to that prototype. It's just as
if you had declared, within a function:

{
struct incomplete_type ;
}
struct incomplete_type {
int x;
int y;
}

The scope of the incomplete declaration is limited to the
brace-enclosed block in which it appears. By the time we see the
complete declaration, the previous incomplete declaration no longer
exists.

When you add your

typedef struct
{ struct thingTag* p;
} entity;

*before* the "show" typedef, you mention "struct thingTag". This is
now treated as a new incomplete type, but since it's not inside the
prototype, its scope extends to the end of the file. (This is
incidental to the declaration of "entity".) Now the compiler sees the
occurrence of "struct thingTag" within the prototype in the "show"
typedef as a reference to the existing incomplete type, rather than as
an implicit declaration of a new one.

If you put the typedef for "entity" *after* the "show" typedef, then
the "struct thingTag" within the prototype declares a new incomplete
type with a limited scope, and the compile warns you about it (because
that's not a useful thing to do). The "struct thingTag" within the
typedef for "entity" *also* declares a new incomplete type (since the
"struct thingTag" from the prototype is out of scope and therefore
doesn't exist), but it's not of such limited scope, so the compiler
doesn't warn you about it.

(This whole business of something being a new declaration if and only
if the thing hasn't already been declared is, IMHO, unfortunate and
confusing, and can mask some serious errors, but there it is.)

If you need a forward declaration of a structure, just do it directly,
not as part of another declaration.

And again, you should seriously consider getting rid of any typedefs
for struct types. By having just one name for the type, you have
fewer things to keep track of.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jun 21 '06 #8
On Wed, 21 Jun 2006 20:31:48 +0000, Keith Thompson wrote:
Duncan Muirhead <no***@this.add ress> writes:
[...] [trimmed]
The first occurrence of "struct thingTag" is inside the typedef for
"show". Since there's been no complete declaration of that type, the
compiler treats it as an implicit declaration of a new incomplete
type; normally, such an incomplete type would be completed later. But
in this case, the new incomplete type appears within a function
prototype, and its scope is limited to that prototype. It's just as
if you had declared, within a function:

{
struct incomplete_type ;
}
struct incomplete_type {
int x;
int y;
}

The scope of the incomplete declaration is limited to the
brace-enclosed block in which it appears. By the time we see the
complete declaration, the previous incomplete declaration no longer
exists.

When you add your

typedef struct
{ struct thingTag* p;
} entity;

*before* the "show" typedef, you mention "struct thingTag". This is
now treated as a new incomplete type, but since it's not inside the
prototype, its scope extends to the end of the file. (This is
incidental to the declaration of "entity".) Now the compiler sees the
occurrence of "struct thingTag" within the prototype in the "show"
typedef as a reference to the existing incomplete type, rather than as
an implicit declaration of a new one.

If you put the typedef for "entity" *after* the "show" typedef, then
the "struct thingTag" within the prototype declares a new incomplete
type with a limited scope, and the compile warns you about it (because
that's not a useful thing to do). The "struct thingTag" within the
typedef for "entity" *also* declares a new incomplete type (since the
"struct thingTag" from the prototype is out of scope and therefore
doesn't exist), but it's not of such limited scope, so the compiler
doesn't warn you about it.

(This whole business of something being a new declaration if and only
if the thing hasn't already been declared is, IMHO, unfortunate and
confusing, and can mask some serious errors, but there it is.)

If you need a forward declaration of a structure, just do it directly,
not as part of another declaration.

And again, you should seriously consider getting rid of any typedefs
for struct types. By having just one name for the type, you have
fewer things to keep track of.


Thank you for your informative reply.
If I understand you correctly, there is a special rule for declarations
of function (pointer) types: any any reference to an undeclared type
declares a new (incomplete) type whose scope is limited to the declaration
of the function type. Within struct (and union) declarations the scope of
any new incomplete type is the file. While this seems unfortunate to me,
if that's the way it is, that's the way it is.

As for typedefs for struct types, I suspect your right, but would say:
I, and indeed the people I've worked with, only ever use the typedef'd
names in code and so having the two names is limited to the type
declaration.
Every now and again I've encountered cases where a struct type is changed
(usually to a primitive, very occasionally to a union). In these cases
were a typedef not used, more edits would have to be made -- though
admittedly they were safe edits in that the compiler reports errors for
any edits not done correctly.
Duncan
Jun 22 '06 #9
Duncan Muirhead <no***@this.add ress> writes:
[...]
Thank you for your informative reply.
If I understand you correctly, there is a special rule for declarations
of function (pointer) types: any any reference to an undeclared type
declares a new (incomplete) type whose scope is limited to the declaration
of the function type. Within struct (and union) declarations the scope of
any new incomplete type is the file. While this seems unfortunate to me,
if that's the way it is, that's the way it is.
More or less.

An appearance of "struct foo" refers to an existing type "struct foo"
if it's been declared; otherwise it creates a new incomplete type.

Any declaration has a scope, depending on where it appears, and does
not exist outside that scope. A function prototype is a scope, so if
"struct foo" appears within a prototype, and there's no existing
visible declaration for "struct foo", then the new incomplete type
"struct foo" isn't visible past the end of the prototype. This is
almost certainly useless; thus the warning.

Scopes are explained in section 6.2.1 of the C99 standard; a free
version can be found by googling n1124.pdf.

There are four kinds of scopes: function, file, block, and function
prototype. (Function scope applies only to labels.)
As for typedefs for struct types, I suspect your right, but would say:
I, and indeed the people I've worked with, only ever use the typedef'd
names in code and so having the two names is limited to the type
declaration.


Then I guess you're stuck with it. I find it cleaner to use just the
struct tag, but it's not worth wholesale re-writing of the code. (And
as I said, my opinion on this point is not shared by everyone.)

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jun 22 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
8234
by: Steven D'Aprano | last post by:
I'm trying to keep an open mind, but I am perplexed about something in Python that strikes me as a poor design. py> def func(a,b): py> print a,b py> func(1) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: func() takes exactly 2 arguments (1 given)
5
5613
by: GitarJake | last post by:
Hello all, Newbie here. SQL 2000, Windows 2000 I'm trying to alter tables in my SQL DB using statements like the following: /* AD_GROUPS */ alter table AD_GROUPS alter column AD_GROUP_NAME nvarchar(64)not null go
0
1067
by: Dilip | last post by:
Vaclav I have taken the liberty to cross-post this microsoft.public.dotnet.languages.vc which has more visibility from MSFT VC++ team. thanks --Dilip Actual post by Vaclav Haisman originally posted at
9
2066
by: Brad | last post by:
I have written some code to manipulate data/records in a MASTER (order header) and DETAIL (order details) tables. What I have written is too extensive to post but essentially trying to: 1. Assign to a datarow (dr1) the first record of the MASTER table 2. Assign to another datarow (dr2) the second record of the MASTER table 3. If dr1.field1 = dr2.field1, then proceed, otherwise do stop 4. Assign to a third datarow (dr3) the first record...
4
2761
by: Peter Ritchie | last post by:
Does anyone know how to suppress a specific warning for a line or block of code in C#? C++ has a nice facility to disable a warning for a block of code with #pragma for warnings that are incorrect or don't apply. For example, the following code generates an CS0628 because CS0628 makes an incorrect assumption that "protected" applies only to inheritance: public sealed class Class { EmbeddedClass utility = new EmbeddedClass();
18
3926
by: Sven | last post by:
Hi, I found a strange behaviour when using the time() function from time.h. Sometimes when it is called, it does not show the correct time in seconds, but an initial value. This time seem to be the time when the program was started the first time. My platform is a DEC machine with Tru64 onboard. A possible explanation could be, that the time() function is called
3
3301
by: Don Burden | last post by:
We've started converting some applications to the .NET 2.0 framework. When compiling in VS 2005, I'm getting a warning on this line: return (unitWidth != null ) ? unitWidth : new Unit("0px"); Looks valid to me, but this gives a warning with "new" underlined saying "warning CS0429: Unreachable expression code detected".
0
5371
by: torpecool | last post by:
Hello Everyone, I have been trying to find information about this issue in the documentation and have not been able to. I hope someone can help. I built a web-based app (PHP) that allows users to upload the contents of a CSV file into database tables. My users have reported that most of the time, everything is fine, but some records do not show up. Although I can see the records by doing
6
2398
by: kepston | last post by:
Hi I have a report which splits invoice costs to various departments and shows a summary. The various divisors and multipliers used in deriving the values for each department, are such that the final figures will not be to 2 decimal places. I decided to use the Round() function so that the calculated figure would equal the formatted figure. I then Summed the rounded figures to reach a total. Occasionally the sum will not equal the actual...
0
9680
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9528
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10456
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10174
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
6788
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5442
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5575
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4118
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3731
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.