Suppressing "Parameter not used" Warning

D

Dave Hansen

Please note crosspost.

Often when writing code requiring function pointers, it is necessary
to write functions that ignore their formal parameters. For example,
a state machine function might take a status input, but a certain
error-handling state might ignore it:

typedef void (*State_Fn)(uint8_t);

void error_state(uint8_t status)
{
NOT_USED(status);

/* code handling error but ignoring status */
}

In another group, a poster asked about defining a macro NOT_USED as
shown above to quiet the compiler warning. His suggested
implementation was

#define NOT_USED(p) ((void)(p))

In this particular case, he noted the compiler he was using would
generate the warning even in the presence of this macro. I suggested
he use

#define NOT_USED(p) ((p)=(p))

He was pleased that it worked, but was concerned that the former
implementation was more widely supported, and that the latter might
generate executable code. I for one had never seen the former before,
though I've often seen the latter (usually not hidden behind a macro),
and I've never seen it actually generate code. At least, not in the
last ten years or so.

So I'm curious. Which form (if either) is more common? Are there any
implementations that will generate executable code for the latter?

Thanks,
-=Dave

-=Dave
 
P

pete

Dave said:
Please note crosspost.

Often when writing code requiring function pointers, it is necessary
to write functions that ignore their formal parameters. For example,
a state machine function might take a status input, but a certain
error-handling state might ignore it:

typedef void (*State_Fn)(uint8_t);

void error_state(uint8_t status)
{
NOT_USED(status);

/* code handling error but ignoring status */
}

In another group, a poster asked about defining a macro NOT_USED as
shown above to quiet the compiler warning. His suggested
implementation was

#define NOT_USED(p) ((void)(p))

In this particular case, he noted the compiler he was using would
generate the warning even in the presence of this macro. I suggested
he use

#define NOT_USED(p) ((p)=(p))

He was pleased that it worked, but was concerned that the former
implementation was more widely supported, and that the latter might
generate executable code.

Non executable code tends to generate warnings.
I for one had never seen the former before,
though I've often seen the latter (usually not hidden behind a macro),
and I've never seen it actually generate code. At least, not in the
last ten years or so.

So I'm curious. Which form (if either) is more common? Are there any
implementations that will generate executable code for the latter?

In distributions file for a sort timing program
my distribution function arguments are of this form:
(e_type *array, size_t n, long unsigned *seed)

but only some of them use the seed for a PRNG.

Others are like this:

void sorted(e_type *a, size_t n, long unsigned *seed)
{
a += n;
while (n-- != 0) {
(*--a).data = n;
}
seed;
}

So, I just make an expression statement out of seed
and that seems to stop the warnings.
 
C

Christopher Benson-Manica

In comp.lang.c Dave Hansen said:
typedef void (*State_Fn)(uint8_t);
void error_state(uint8_t status)
{
NOT_USED(status);
/* code handling error but ignoring status */
}

Why not just

void error_state( uint8_t ) /* don't care about formal parameter */
{
/* code */
}

? (I'm not enough of a guru to answer your real question.)
 
S

Skarmander

Christopher said:
Why not just

void error_state( uint8_t ) /* don't care about formal parameter */
{
Because that's not legal C. If it were, we obviously wouldn't need any
hacks. You can do this in prototypes; in C++ you can also do it in
definitions. Not in C, however.

S.
 
E

Eric Sosman

Dave Hansen wrote On 10/03/05 10:13,:
Please note crosspost.

Often when writing code requiring function pointers, it is necessary
to write functions that ignore their formal parameters. For example,
a state machine function might take a status input, but a certain
error-handling state might ignore it:

typedef void (*State_Fn)(uint8_t);

void error_state(uint8_t status)
{
NOT_USED(status);

/* code handling error but ignoring status */
}

In another group, a poster asked about defining a macro NOT_USED as
shown above to quiet the compiler warning. His suggested
implementation was

#define NOT_USED(p) ((void)(p))

In this particular case, he noted the compiler he was using would
generate the warning even in the presence of this macro. I suggested
he use

#define NOT_USED(p) ((p)=(p))

He was pleased that it worked, but was concerned that the former
implementation was more widely supported, and that the latter might
generate executable code. I for one had never seen the former before,
though I've often seen the latter (usually not hidden behind a macro),
and I've never seen it actually generate code. At least, not in the
last ten years or so.

So I'm curious. Which form (if either) is more common? Are there any
implementations that will generate executable code for the latter?

First, there is no sure-fire way to prevent compilers
from issuing diagnostics. The compiler is entitled to
grouse about anything it chooses, provided it accepts code
that does not actually contravene the Standard. It can
warn about spellnig errors in comennts, or about inconsistent
indentation levels. The requirement "No warnings from any
compiler" is not ultimately tenable.

FWIW, the `(void)p' formulation seems to be widespread.
Even if a compiler complains about it, a human reader will
see immediately that it was in fact the programmer's intent
that `p' remain unused -- the programmer may have made a
mistake, but at least it was not one of simple inattention.

I don't think `(p)=(p)' is a wonderful idea. If `p' is
volatile the generated code must perform both the read and the
write. If `p' is `const' the compiler is required to issue a
diagnostic, so you're no better off than when you started --
worse, if anything. Of course, `const'-qualified function
parameters are fairly unusual and `volatile' parameters are
exceedingly rare, but the possibilities exist.

In any case, hiding the actual trickery behind a NOT_USED
macro seems a good idea: you can re-#define NOT_USED as part
of your adaptation to each new compiler that comes along,
using whatever compiler-specific dodge seems to work best.
 
A

Anonymous 7843

In another group, a poster asked about defining a macro NOT_USED as
shown above to quiet the compiler warning.

An alternative would be to invoke the compiler using a flag or option
that disables the unused variable/parameter warning.

However, it's good practice to turn the warning back on every once
in a while and see if any unexpected unused thingies have crept into
the code.
 
D

David Brown

Dave said:
Please note crosspost.

Often when writing code requiring function pointers, it is necessary
to write functions that ignore their formal parameters. For example,
a state machine function might take a status input, but a certain
error-handling state might ignore it:

typedef void (*State_Fn)(uint8_t);

void error_state(uint8_t status)
{
NOT_USED(status);

/* code handling error but ignoring status */
}

In another group, a poster asked about defining a macro NOT_USED as
shown above to quiet the compiler warning. His suggested
implementation was

#define NOT_USED(p) ((void)(p))

In this particular case, he noted the compiler he was using would
generate the warning even in the presence of this macro. I suggested
he use

#define NOT_USED(p) ((p)=(p))

He was pleased that it worked, but was concerned that the former
implementation was more widely supported, and that the latter might
generate executable code. I for one had never seen the former before,
though I've often seen the latter (usually not hidden behind a macro),
and I've never seen it actually generate code. At least, not in the
last ten years or so.

So I'm curious. Which form (if either) is more common? Are there any
implementations that will generate executable code for the latter?

Thanks,
-=Dave

-=Dave

I use the first version, a cast-to-void macro. It works fine for gcc
(various ports).
 
G

Grant Edwards

#define NOT_USED(p) ((void)(p))
[...]
#define NOT_USED(p) ((p)=(p))
[...]

So I'm curious. Which form (if either) is more common? Are there any
implementations that will generate executable code for the latter?
I use the first version, a cast-to-void macro. It works fine
for gcc (various ports).

Very slightly OT, but I just use gcc's __attribute__((unused)).
I realize it's not-portable to other compilers, but...

1) In my applications so much of the code is platform-specific
that it just doesn't matter.

2) I've used nothing but gcc for embedded work for the past 6
or 7 years anyway.
 
C

Christopher Benson-Manica

In comp.lang.c Skarmander said:
Because that's not legal C. If it were, we obviously wouldn't need any
hacks. You can do this in prototypes; in C++ you can also do it in
definitions. Not in C, however.

My apologies; I use C++, and this was a difference of which I was not
aware. Thanks.
 
O

Old Wolf

Dave said:
In another group, a poster asked about defining a macro NOT_USED as
shown above to quiet the compiler warning. His suggested
implementation was

#define NOT_USED(p) ((void)(p))

In this particular case, he noted the compiler he was using would
generate the warning even in the presence of this macro. I suggested
he use

#define NOT_USED(p) ((p)=(p))


So I'm curious. Which form (if either) is more common? Are there
any implementations that will generate executable code for the latter?

Yes, the compiler might warn that 'p' is assigned a value which
is never used. And it might also warn about reading an uninitialized
variable.

One compiler I use has this definition:

#define NOT_USED(junk) { (volatile typeof(junk))junk = junk; }
 
K

Keith Thompson

Old Wolf said:
Yes, the compiler might warn that 'p' is assigned a value which
is never used. And it might also warn about reading an uninitialized
variable.

In fact, strictly speaking, this could invoke undefined behavior if p
really hasn't been initialized. Since it's a parameter (at least in
the context intended by the OP), that would happen only if the caller
passes an uninitialized value, so it would require some additional
smarts by the compiler to detect the problem.

On most real-world systems, this isn't going to cause any visible
problems, but it's possible that certain pointer values can cause a
trap when you try to load them into a register, even if there's no
attempt to dereference the value. The same could apply to any type
that can have trap representations.

Hiding this behind a NOT_USED macro is a good idea. The definition of
the macro can probably be made to vary depending on what system you're
on, using the usual twisty maze of #ifdefs method.

The ((p)=(p)) trick is ok if you make sure p is always initialized,
even to a meaningless value.

As others have mentioned, there is no portable way to control specific
warnings that will work across implementations.
 
M

Mark Borgerson

Yes, the compiler might warn that 'p' is assigned a value which
is never used. And it might also warn about reading an uninitialized
variable.

One compiler I use has this definition:

#define NOT_USED(junk) { (volatile typeof(junk))junk = junk; }
Metrowerks Codewarrior has the

#pragma unused (varname)

construct to solve this problem. I'm surprised that other compilers
don't have the same facility.

Mark Borgerson
 
T

Thad Smith

Dave said:
Often when writing code requiring function pointers, it is necessary
to write functions that ignore their formal parameters. For example,
a state machine function might take a status input, but a certain
error-handling state might ignore it:

typedef void (*State_Fn)(uint8_t);

void error_state(uint8_t status)
{
NOT_USED(status);

/* code handling error but ignoring status */
}

In another group, a poster asked about defining a macro NOT_USED as
shown above to quiet the compiler warning. His suggested
implementation was

#define NOT_USED(p) ((void)(p))

In this particular case, he noted the compiler he was using would
generate the warning even in the presence of this macro.

I have used a void cast for some compilers. For another, I was
successful with

#define UNUSED(x) if(x);

Thad
 
A

Alexei A. Frounze

....
....
I use the first version, a cast-to-void macro. It works fine for gcc
(various ports).

Also: borland, watcom, a few less popilar ones. I don't remember about
msvc++. Probably too.
Alex
 
A

Alexei A. Frounze

....
I have used a void cast for some compilers. For another, I was
successful with

#define UNUSED(x) if(x);

Nice, though some clever compiler could warn here whether or not you're sure
it's what you intend to do, whether or not this code has any effect.

Alex
 
D

David Brown

Mark said:
Metrowerks Codewarrior has the

#pragma unused (varname)

construct to solve this problem. I'm surprised that other compilers
don't have the same facility.

Mark Borgerson

The trouble with such pragmas is that they are completely non-portable.
As Grant Edwards said, gcc has an equivalent (using an attribute,
which is gcc prefers over pragmas). Often non-portability is not a
problem, since there are so many other non-portable aspects to typical
embedded systems (and in the case of gcc, it is at least portable to a
few dozen other gcc ports).
 
D

David Brown

Grant said:
#define NOT_USED(p) ((void)(p))
[...]
#define NOT_USED(p) ((p)=(p))
[...]

So I'm curious. Which form (if either) is more common? Are there any
implementations that will generate executable code for the latter?

I use the first version, a cast-to-void macro. It works fine
for gcc (various ports).


Very slightly OT, but I just use gcc's __attribute__((unused)).
I realize it's not-portable to other compilers, but...

1) In my applications so much of the code is platform-specific
that it just doesn't matter.

2) I've used nothing but gcc for embedded work for the past 6
or 7 years anyway.

Also OT, but the warning that bugs me most with gcc is "warning: will
never be executed" on code that gets removed by the optimiser. If I've
written code that really cannot ever be executed, it's (almost
certainly) a mistake, so I want the compiler to tell me. But on code
like this:

if (test()) {
doThis();
doThat();
} else {
doSomethingElse();
doThat();
}

gcc will combine the two "doThat()" calls (which is good), and then warn
that one of the "will never be executed", which is bad.

If you know any good ideas to get working "will never be executed"
warnings, even if it is "wait for gcc 4.1.x", I'd love to hear them.
 
B

Bill Davy

Dave Hansen said:
Please note crosspost.

snip snip

void error_state(uint8_t /* status */)

I prefer to leave the argument there as it should make code easier to
comprehend. Commenting it out does not need comments.
 
F

Flash Gordon

Bill said:
snip snip

void error_state(uint8_t /* status */)

I prefer to leave the argument there as it should make code easier to
comprehend. Commenting it out does not need comments.

As noted by an earlier poster, that is not valid for a C function
definition (declaration yes, but not definition which is what was being
discussed).

If you want to discus what you do in C++ (or any language other than C)
then please remove comp.lang.c from the crosspost.
 
M

Michael N. Moran

David said:
if (test()) {
doThis();
doThat();
} else {
doSomethingElse();
doThat();
}

gcc will combine the two "doThat()" calls (which is good), and then warn
that one of the "will never be executed", which is bad.

If you know any good ideas to get working "will never be executed"
warnings, even if it is "wait for gcc 4.1.x", I'd love to hear them.

Hmmm. I tried this with a couple of GCC versions at default
and -O[23] optimization levels (cross and native) and saw no
such warning. What options/versions are you using?

--
Michael N. Moran (h) 770 516 7918
5009 Old Field Ct. (c) 678 521 5460
Kennesaw, GA, USA 30144 http://mnmoran.org

"So often times it happens, that we live our lives in chains
and we never even know we have the key."
The Eagles, "Already Gone"

The Beatles were wrong: 1 & 1 & 1 is 1
 

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
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top