Help on C code

P

PranjalMishra

I am confused about the code snippet given below.

int main(int argc, char** argv)
{
AA( main )

USENOT( argc );
USENOT( argv );

exit( 0 );

return;
}

whereas AA is defined as any one of the following based on some
condition

#define AA(a) ar[i++] = #a;
or
#define AA(a) printf(#a "\n");
or
#define AA(a) ;

ar is defined as
extern char *ar[];

USENOT is defined as
#define USENOT(x) (x=x)

1.Can somebody explain what's happening after entering the function
main in all the three cases of the values of AA.

2. what may be the USENOT's purpose.
 
M

Mark A. Odell

(e-mail address removed) (PranjalMishra) wrote in

I am confused about the code snippet given below.

int main(int argc, char** argv)
{
AA( main )

USENOT( argc );
USENOT( argv );

exit( 0 );

return;
}

whereas AA is defined as any one of the following based on some
condition

#define AA(a) ar[i++] = #a;
or
#define AA(a) printf(#a "\n");
or
#define AA(a) ;

ar is defined as
extern char *ar[];

USENOT is defined as
#define USENOT(x) (x=x)

1.Can somebody explain what's happening after entering the function
main in all the three cases of the values of AA.

Just run the program yourself compiled the 3 different ways.
2. what may be the USENOT's purpose.

To quiet the compiler warning about argc and argv not being used. The
author might better have defined main() as int main(void) in this case.
 
D

David Logan

PranjalMishra said:
I am confused about the code snippet given below.

int main(int argc, char** argv)
{
AA( main )

USENOT( argc );
USENOT( argv );

exit( 0 );

return;
}

whereas AA is defined as any one of the following based on some
condition

#define AA(a) ar[i++] = #a;
or
#define AA(a) printf(#a "\n");
or
#define AA(a) ;

ar is defined as
extern char *ar[];

USENOT is defined as
#define USENOT(x) (x=x)

1.Can somebody explain what's happening after entering the function
main in all the three cases of the values of AA.

2. what may be the USENOT's purpose.

The snippet is basically giving you a function trace. In the first
instance, it is saving the name of the function in an array of strings.
You can then traverse that array at will. If:

#define AA(a) ar[i++] = #a;
AA(main)

the precompiler will expand the AA macro, replacing "a", (and #a is a
"stringized" version of the parameter) sending this to the compiler:

ar[i++] = "main";

This will not compile if the variable 'i' is not also defined, of course.

So the second should now be obvious:

#define AA(a) printf(#a "\n");
AA(main)

the precompiler will send:
printf("main" "\n");

And, the third case will simply eat the parameter, since the macro is empty:

#define AA(a)
AA(main)

will send:
(nothing)

I expect USENOT is a placeholder for a macro that has not yet been
defined, since it really does nothing useful.

David Logan
 
M

Mark A. Odell

I expect USENOT is a placeholder for a macro that has not yet been
defined, since it really does nothing useful.

No, it quiets compiler warnings about unused vars.
 
D

David Logan

Mark said:
No, it quiets compiler warnings about unused vars.

I saw your post on that. I would never have thought of that. I would
have expected a more logical explanation :)

David Logan
 
M

Mark A. Odell

(e-mail address removed) (Richard Tobin) wrote in

Or maybe it generates compiler warnings about pointless assignments.

I didn't say it was a good implementation of the macro :). The RTOS I use
has a static variable that it assigns the unused parameter to. Their macro
is better named too:

/* Some RTOS header file
*/
extern unsigned long rtos_unused_parameter;
#define UNUSED_PARAMETER(x) rtos_unused_parameter = (unsigned long) (x)
 
D

Dan Pop

In said:
I saw your post on that. I would never have thought of that. I would
have expected a more logical explanation :)

It's logical enough. Consider the following program:

#include <stdio.h>

int main(int argc, char **argv)
{
while (*argv != NULL) puts(*argv++);
return 0;
}

Some compilers/lints will warn that argc is declared but never used.
You have to choose between using the option that shuts up the warning
(or not using the option that enables it) and doing some dummy operation
with argc. If you opt for the latter approach, hiding the otherwise
meaningless argc = argc behind a macro usually named NOTUSED, renders
your intent more obvious to the human reader, as well as getting rid of
the unwanted warning.

Dan
 
D

Dan Pop

In said:
Odd - it doesn't seem to work with my compiler.

It works for the very popular gcc -Wall -W invocation (and probably for
many others).

Of course, when it comes to compiler warnings, a program construct that
shuts up one undesired warning on one compiler may have no effect on
another compiler or even trigger another undesired warning.

Dan
 
?

=?iso-8859-1?q?Nils_O=2E_Sel=E5sdal?=

I am confused about the code snippet given below.

int main(int argc, char** argv)
{
AA( main )

USENOT( argc );
USENOT( argv );

exit( 0 );

return;
}

whereas AA is defined as any one of the following based on some
condition

Lets see what we get running it through a preprocessor:
#define AA(a) ar[i++] = #a;
int main(int argc, char** argv)
{
ar[i++] = "main";

(argc=argc);
(argv=argv);

exit( 0 );

return;
}
or
#define AA(a) printf(#a "\n");
int main(int argc, char** argv)
{
printf("main" "\n");

(argc=argc);
(argv=argv);

exit( 0 );

return;
}
or
#define AA(a) ;
int main(int argc, char** argv)
{
;

(argc=argc);
(argv=argv);

exit( 0 );

return;
}
 
O

Old Wolf

David Logan said:
I saw your post on that. I would never have thought of that. I would
have expected a more logical explanation :)

Not very 'portable', of course; on some compilers it would merely
replace the "unused variable" warning with "statement has no effect".
 
E

Emmanuel Delahaye

In said:
I am confused about the code snippet given below.

int main(int argc, char** argv)
{
AA( main )

USENOT( argc );
USENOT( argv );

exit( 0 );

return;
}

whereas AA is defined as any one of the following based on some
condition

#define AA(a) ar[i++] = #a;

Debug mode: means "put the address of the string made from the parameter in
some array of pointers to char, and increment some index" (seems to have no
bound check. Bad coding.). Sounds like a trace device for interrupt code...

Note : In a macro definition, '#' changes the parameter of a macro to a
string literal
or
#define AA(a) printf(#a "\n");

Debug mode: Explicitely sends a line to stdout with the name given as
parameter.
or
#define AA(a) ;

Release mode: Do nothing.

Note AA is a very bad name (however, not worst than FOO or BAR)
ar is defined as
extern char *ar[];

As I guessed... 'i' should be a global too... which is a VERY bad name for a
global.

Hint: globals are shadowed by locals with the same name...
USENOT is defined as
#define USENOT(x) (x=x)

A twisted way of writing:
#define USENOT(x) (void)(x)

Or directly

(void)(x);

into the source code.

It's a way to mute the compiler about the 'variable or parameter defined but
not used' warning.

IMO, this warning is useful and should not be muted in debug mode. (Hence,
after all, the macro appears to be useful...)
 
F

Fred L. Kleinschmidt

Mark A. Odell said:
I believe it was intended to.

To quiet the compiler about unused arguments, I use the /* ARGSUSED */
comment immediately before the function definition. Seems to quiet most
compilers:
/* ARGSUSED */
int main( int argc, char** argv) {
....
}
 
M

Mark A. Odell

To quiet the compiler about unused arguments, I use the /* ARGSUSED */
comment immediately before the function definition. Seems to quiet most
compilers:
/* ARGSUSED */
int main( int argc, char** argv) {
...
}

How many compilers does this comment work with? It's not part of the ISO C
spec. so it's not portable.
 
A

Arthur J. O'Dwyer

How many compilers does this comment work with? It's not part of
the ISO C spec. so it's not portable.

It doesn't work with gcc (but I guess you knew that). As to
portability, it's a lot more sensible than the (argc=argc) version,
since at least it won't generate *extra* warnings or code if it's
not recognized. Since the Standard doesn't mention warnings for unused
arguments, obviously there is no "portable" way to quiet compiler
warnings. (*Any* compiler warnings, pedantically speaking.)

Of course, the best approach (assuming you can't or won't ignore
or disable the spurious warning by other means) is a hybrid of Fred's
and the usual method:

/* Quiet compiler warning about unused arguments */
(void)argc;
(void)argv;

-Arthur
 
R

red floyd

Fred L. Kleinschmidt said:
To quiet the compiler about unused arguments, I use the /* ARGSUSED */
comment immediately before the function definition. Seems to quiet most
compilers:
/* ARGSUSED */
int main( int argc, char** argv) {
...
}

ARGSUED is historical. It was used to tell lint(1) to shut up.
 

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,143
Messages
2,570,822
Members
47,368
Latest member
michaelsmithh

Latest Threads

Top