How to fix compiler warning

K

Keith Thompson

Ian Collins said:
pete wrote: [...]
I don't see void main() as being as more or less correct
on freestanding implementations which define void main(),
than it is on hosted implementations which define void main().
Section 5.1.2.2.1 of the standard does.

It says that main shall be defined as 'int main(void)', or as
'int main(int argc, char *argv[])', "or in some other
implementation-defined manner".

So 'void main(void)' is "correct" on an implementation (either hosted
for freestanding) that supports it.

By contrast, 'int main(void)' is correct on any hosted implementation
(and may or may not be correct on a given freestanding
implementation).

I was going to say which one of you I agree with, but the disagreement
is over words, not over what those words refer to, so I won't bother.
 
J

jacob navia

Christopher said:
I would think that an implementation worth its salt would provide a
warning level at which it did issue a diagnostic for void main(). Are
there any major implementations which cannot be coerced into doing so?

I added a warning for
void main(void)
{
}

since lcc-win32 got into an obscure bug...

C99 mandates that main should return zero even if the programmer
doesn't explicitly write a return statement.

If you declare main as a void function however,
the compiler would try to make a void function return zero
as result!!!

A user warned me about this: the compiler crashed when it
saw

void main(void)
{}

I fixed it by ignoring the void statement. And added a
warning with a higher warning level.
 
P

pete

Richard said:
pete said:


In C90, it's wrong on hosted implementations. Freestanding
implementations are free to insist on their own entry point syntax if
they wish, but C90 implementations must provide int main(int, char **)
and correct C90 programs must use int main(int char **) - not to do so
renders the behaviour of the program undefined.

In C99, the situation has not changed in the freestanding world - and,
in practice, it hasn't actually changed in the hosted world either,
since implementations were always free to document alternate entry
point syntax.
The only difference is academic - in C99, if your program
takes advantage of an implementation's documented alternative, your
program's behaviour *under that implementation* is
implementation-defined rather than undefined.

Just exactly as it is for the freestanding implementations
that you refer to.
If you try to port it,
however, this academic distinction vanishes, and you're right back to
undefined behaviour again.

Just exactly as it is for the freestanding implementations
that you refer to.
 
F

Flash Gordon

jacob navia wrote, On 25/08/07 21:16:
I added a warning for
void main(void)
{
}

Good :)
since lcc-win32 got into an obscure bug...

C99 mandates that main should return zero even if the programmer
doesn't explicitly write a return statement.

If you declare main as a void function however,
the compiler would try to make a void function return zero
as result!!!

A user warned me about this: the compiler crashed when it
saw

void main(void)
{}

You could have claimed it was not a bug because it did not affect
conformance to the C standard. You are explicitly allowed to fail to
compile a program that unconditionally invokes undefined behaviour, and
crashing counts.
I fixed it by ignoring the void statement. And added a
warning with a higher warning level.

Shucks. Still, even an obsolete compiler that crashes on void main() is
another reason not to use it :)
 
B

Barry Schwarz

I have a macro that I use across the board for freeing ram. I'd like to
clean up my code so I don't get these warnings.

#define sfree(x) _internal_sfree((void **)&x)
#define _internal_sfree(x) ({ if(x && *x) { free(*x); *x=NULL; } })

There is no guarantee that casting &y to void** and then dereferencing
it will produce the void* containing the original value of y that you
want. Consider the case below where y is a int* and let sizeof
(void*) be 8 while all other pointers are 4.

There is even no guarantee that the value &x is properly aligned for a
void** value.
void main() {
char *x = (char *) malloc(10);
int *y = (int *) malloc(10);

sfree(x);
sfree(y);
}

results in:

warning: dereferencing type-punned pointer will break strict-aliasing
rules


Remove del for email
 
C

Chris Hills

Christopher Benson-Manica said:
[comp.lang.c] Richard Heathfield said:
Ian Collins said:
If you didn't get a warning for this, crank up the warning level!
Whilst it's wrong (except on some freestanding implementations), it
isn't a syntax error or a constraint violation. Implementations need
not diagnose it (although some choose to do so).

I would think that an implementation worth its salt would provide a
warning level at which it did issue a diagnostic for void main(). Are
there any major implementations which cannot be coerced into doing so?

Yes, quite a few.

Most embedded cross compilers do not and should not.
In fact it is more useful if they give a warning to
int main()
as there is nothing to return to.

However I agree that in the hosted world a warning should be given.

These days I suspect the majority of C use is in the embedded world.
 
P

Philip Potter

Barry said:
There is no guarantee that casting &y to void** and then dereferencing
it will produce the void* containing the original value of y that you
want. Consider the case below where y is a int* and let sizeof
(void*) be 8 while all other pointers are 4.

Such an implementation would not be conforming AFAIK. sizeof(void *) ==
sizeof(char *).
There is even no guarantee that the value &x is properly aligned for a
void** value.

Values do not have alignment. This is why the following code works even though
shorts may have alignments that longs may not:

#include <stdio.h>
int main(void) {
short value = 10;
long lval = (long) value;
printf("%d\n",lval); /* Or should it be %ld? */
return 0;
}

Phil
 
P

Philip Potter

Chris said:
Christopher Benson-Manica said:
[comp.lang.c] Richard Heathfield said:
Ian Collins said:
If you didn't get a warning for this, crank up the warning level!
Whilst it's wrong (except on some freestanding implementations), it
isn't a syntax error or a constraint violation. Implementations need
not diagnose it (although some choose to do so).

I would think that an implementation worth its salt would provide a
warning level at which it did issue a diagnostic for void main(). Are
there any major implementations which cannot be coerced into doing so?

Yes, quite a few.

Most embedded cross compilers do not and should not.
In fact it is more useful if they give a warning to
int main()
as there is nothing to return to.

However I agree that in the hosted world a warning should be given.

These days I suspect the majority of C use is in the embedded world.

That depends on how you define "the majority", I guess. I accept that your
statement may be correct for usage of C to get work done. But for learners of C,
I think the majority would be using hosted implementations on ordinary PCs.

Besides, I'm working on an embedded platform at the moment and the
implementation is hosted, not freestanding. (You just have to be careful not to
use any of the standard library calls (of which printf() is one) which may swell
your binary beyond 64Kb...)

Phil
 
B

Barry Schwarz

Such an implementation would not be conforming AFAIK. sizeof(void *) ==
sizeof(char *).

True. Let sizeof(void*) and sizeof(char*) be 8 while others are 4 and
the point remains valid.
Values do not have alignment. This is why the following code works even though
shorts may have alignments that longs may not:

Values assigned to pointers must satisfy alignment issues. &x is an
expression with type pointer to something. From 6.3.2.3-7:

"A pointer to an object or incomplete type may be converted to a
pointer to a different object or incomplete type. If the resulting
pointer is not correctly aligned for the pointed-to type, the behavior
is undefined."
#include <stdio.h>
int main(void) {
short value = 10;
long lval = (long) value;

All you have done here is cast an integer value to another integer
value of greater rank. This has nothing to do with alignment.

If you had said
long lval = *(long*)&value;
you would be addressing the issue at hand and in fact invoking
undefined behavior on all systems where sizeof(long)>sizeof(short).
The UB is the result not only of possible alignment issues but also of
accessing bytes beyond the end of value.
printf("%d\n",lval); /* Or should it be %ld? */
Yes.

return 0;
}


Remove del for email
 
C

Chris Torek

Most embedded cross compilers do not [warn about "void main"]

That may well be the case, although I cannot speak for "most" or even
"many".
and should not.

Here, I disagree: "should" or "should not" is too strong, and I think
I disagree even more strongly with this:
In fact it is more useful if they give a warning to
int main()
as there is nothing to return to.

Often enough, there *is* something to return to: the assembly code
that calls the startup routine. This may well just reboot, if that
suffices for an error recovery method.

Since I, in embedded environments, tend to name my "C startup
routine" start() (not main()), it does not affect me one way or
another what any given compiler thinks of the symbol "main". I
recommend this practice to all embedded-systems writers: do not
use main() at all, unless it will have return type "int" and the
two Standard C arguments.
However I agree that in the hosted world a warning should be given.

These days I suspect the majority of C use is in the embedded world.

Perhaps. Of course, on vxWorks 6.x, RTPs are entered at main()
with the two Standard C arguments (plus, admittedly, several more
that one can use or ignore as desired -- specifically "char **envp",
a la Unix-like systems, and "void *aux", which is ... difficult to
describe) and the return value from main() is made available to
the task that collects the RTP's exit status.
 
C

Chris Hills

Chris Torek said:
Most embedded cross compilers do not [warn about "void main"]

That may well be the case, although I cannot speak for "most" or even
"many".
and should not.
Here, I disagree: "should" or "should not" is too strong, and I think
I disagree even more strongly with this:

Then we shall have to disagree.

Often enough, there *is* something to return to: the assembly code
that calls the startup routine. This may well just reboot, if that
suffices for an error recovery method.

All the asm start up code I have seen is a linear piece of code whose
final instruction is something like "jmp _main" There is no return
point.

More to the point return statement in main will have nothing to return
to. It will be completely undefined (unless there is an OS)

Despite what the embedded OS vendors will have you believe the use of an
OR or RTOS in embedded systems is still quite uncommon.

So where is this "return" supposed to go? Having a return that does
something indeterminate is dangerous in many embedded systems.
Therefore there should be no return.

If it gets that far wrong you need a re-boot or of course an infinite
lop and let the watchdog take over.

Doing a return from many is just dangerous as the program exits into the
ether....
Since I, in embedded environments, tend to name my "C startup
routine" start() (not main()), it does not affect me one way or
another what any given compiler thinks of the symbol "main". I
recommend this practice to all embedded-systems writers: do not
use main() at all, unless it will have return type "int" and the
two Standard C arguments.

Fair enough. However many (most?) of the embedded debug tools look for
"main" as a start point so often you get no choice.
 
C

CBFalconer

Chris said:
.... snip ...

All the asm start up code I have seen is a linear piece of code
whose final instruction is something like "jmp _main" There is
no return point.

Sounds as if you have been stuck with poor systems. Everything I
have built, or designed, called main (or the appropriate
equivalent), and either rebooted or halted if there was no
controlling shell to return to. Before any halt they would emit an
alerting message if the hardware permitted.
 

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,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top