What gcc options guarantee more portable C code

L

lovecreatesbeauty

On gcc, which version of C standard has the most compliant: -c89, -ansi
or c99? For more portable C code, which options should be applied to
compilation?

Can the following options guarantee the most portable C code for
different environment?

gcc -ansi -pedantic -Wall test.c
 
M

Marc Boyer

Le 15-06-2006 said:
On gcc, which version of C standard has the most compliant: -c89, -ansi
or c99? For more portable C code, which options should be applied to
compilation?

Can the following options guarantee the most portable C code for
different environment?

gcc -ansi -pedantic -Wall test.c

Can't you read the documentation of GCC ?
To compile c89 code, the option is -std=c89.
Support of c99 is not universal today, so, when looking at
'portability', you could restrict yourself to c89.

Other options are there to warn you when you compile some code
that gcc find suspect.

Marc Boyer
 
C

CBFalconer

lovecreatesbeauty said:
.... snip ...
Can the following options guarantee the most portable C code for
different environment?

gcc -ansi -pedantic -Wall test.c

Try "gcc -W -Wall -ansi -pedantic -Wwrite-strings -Wfloat-equal"
 
L

lovecreatesbeauty

Marc said:
Can't you read the documentation of GCC ?
To compile c89 code, the option is -std=c89.
Support of c99 is not universal today, so, when looking at
'portability', you could restrict yourself to c89.
Other options are there to warn you when you compile some code
that gcc find suspect.

Thank you. But there are total 8933 lines in gcc manual document in
Debian Linux 3.1. Your expertise suggestion can just point out the
right selection from among nearly ten thousand lines of information.
Try "gcc -W -Wall -ansi -pedantic -Wwrite-strings -Wfloat-equal"

Thank CBFalconer for the kind help.

lovecreatesbeauty
 
T

tomstdenis

CBFalconer said:
Try "gcc -W -Wall -ansi -pedantic -Wwrite-strings -Wfloat-equal"

I dunno if that includes shadows but throw in -Wshadow as well if it
doesn't.

Tom
 
L

lovecreatesbeauty

I dunno if that includes shadows but throw in -Wshadow as well if it
doesn't.

I check gcc manual again and find that -Wall doesn't cover -Wshadow.
I'm sorry if I misunderstood you.

lovecreatesbeauty
 
T

tomstdenis

lovecreatesbeauty said:
I check gcc manual again and find that -Wall doesn't cover -Wshadow.
I'm sorry if I misunderstood you.

Then add it. -Wshadow isn't for portability but a lot of beginners
seem to make that mistake, e.g.

int x = 5;
while (somethingelse != 0) {
int x;
for (x = 0; x < 17; x++) { ... }
}
printf("Why is %d==5 it should be 17!!!???\n", x);

Clearly that's a bit contrived but when you use variables like i, j, x,
y, z as loop counters it's trivial to re-use them in nested blocks.

For my code I typically use

-Wall -Wsign-compare -W -Wshadow -Wno-unused-parameter

With at least -O2 or -O3. Turning on optimization is required for
several warnings to fully work.

so if you used

--std=c99 -pedantic -O2 -Wall -Wsign-compare -W -Wshadow
-Wno-unused-parameter

You're likely to catch most common programming mistakes as well as
standards violations. The trick is to not only use these flags but
then ADDRESS the diagnostics raised. Too many people use -Wall then
ignore all the output because "my code is right" syndrome kicks in.

Tom
 
A

Andrew Poelstra

I dunno if that includes shadows but throw in -Wshadow as well if it
doesn't.

This from Richard Heathfield:
gcc -W -Wall -ansi -pedantic -Wformat-nonliteral -Wcast-align -Wpointer-arith
-Wbad-function-cast -Wmissing-prototypes -Wstrict-prototypes
-Wmissing-declarations -Winline -Wundef -Wnested-externs -Wcast-qual
-Wshadow -Wconversion -Wwrite-strings -Wno-conversion

(You'll have to un-linewrap that a fair bit).
 
C

CBFalconer

I dunno if that includes shadows but throw in -Wshadow as well if
it doesn't.

It doesn't, and adding it is a bad idea. There are times when you
deliberately want to hide an outer scoped identifier, and shadowing
it with a local one is the ideal method.

....
int important; /* critical to the rest of the system */
....
int mybiglongfunctionNOTusingimportant(params) {
....
int local;
int impossible;
...
important = whatever; /* absent minded typo for impossible */
...
}

The above will be perfectly legal coding, but buggy. The bug will
cause total implosion elsewhere. By simply relabelling impossible
as important we prevent such from ever occuring. Shadow good, bug
bad.
 
J

John Bode

lovecreatesbeauty said:
On gcc, which version of C standard has the most compliant: -c89, -ansi
or c99? For more portable C code, which options should be applied to
compilation?

Can the following options guarantee the most portable C code for
different environment?

gcc -ansi -pedantic -Wall test.c

No, because "standard-compliant" does not necessarily imply "portable."
Code that assumes a particular endianness or uses bitfields to model
architecture-specific structures or relies on a platform-specific API
may compile cleanly with the above command, yet still not be portable
(or at least not maximally so).

Don't get me wrong, it's good practice, and it will catch some obvious
errors that may affect portability, but it won't guarantee that the
code is portable.
 
T

tomstdenis

CBFalconer said:
It doesn't, and adding it is a bad idea. There are times when you
deliberately want to hide an outer scoped identifier, and shadowing
it with a local one is the ideal method.

...
int important; /* critical to the rest of the system */
...
int mybiglongfunctionNOTusingimportant(params) {
....
int local;
int impossible;
...
important = whatever; /* absent minded typo for impossible */
...
}

The above will be perfectly legal coding, but buggy. The bug will
cause total implosion elsewhere. By simply relabelling impossible
as important we prevent such from ever occuring. Shadow good, bug
bad.

I don't get the comment. -Wshadow kicks in if you had "important" as a
local variable to the current nesting level. You don't so that's not a
shadowing diagnostic [one way or another].

Also it's bad practice to use locals which you know are going to be
named as globals [or at least externably linkable] elsewhere.

This is why you don't have

void func(void)
{
int fopen = 4;

// ... blah blah blah
}

Tom
 
S

spibou

CBFalconer said:
It doesn't, and adding it is a bad idea. There are times when you
deliberately want to hide an outer scoped identifier, and shadowing
it with a local one is the ideal method.

...
int important; /* critical to the rest of the system */
...
int mybiglongfunctionNOTusingimportant(params) {
....
int local;
int impossible;
...
important = whatever; /* absent minded typo for impossible */
...
}

The above will be perfectly legal coding, but buggy. The bug will
cause total implosion elsewhere. By simply relabelling impossible
as important we prevent such from ever occuring. Shadow good, bug
bad.

I don't get the comment. -Wshadow kicks in if you had "important" as a
local variable to the current nesting level. You don't so that's not a
shadowing diagnostic [one way or another].

I think he was trying to give an example where you *would* want to use
shadowing ie name the variable inside the function important instead of
impossible.
 
C

CBFalconer

CBFalconer wrote:
It doesn't, and adding it is a bad idea. There are times when you
deliberately want to hide an outer scoped identifier, and shadowing
it with a local one is the ideal method.

...
int important; /* critical to the rest of the system */
...
int mybiglongfunctionNOTusingimportant(params) {
....
int local;
int impossible;
...
important = whatever; /* absent minded typo for impossible */
...
}

The above will be perfectly legal coding, but buggy. The bug will
cause total implosion elsewhere. By simply relabelling impossible
as important we prevent such from ever occuring. Shadow good, bug
bad.

I don't get the comment. -Wshadow kicks in if you had "important"
as a local variable to the current nesting level. You don't so
that's not a shadowing diagnostic [one way or another].

I think he was trying to give an example where you *would* want to
use shadowing ie name the variable inside the function important
instead of impossible.

Exactly. It is somewhat analagous to the practice of putting the
constant first in an equality test to have the compiler help find
multilegged creatures:

if (123 == foo) ...

--
Some informative links:
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html
 
K

Keith Thompson

CBFalconer said:
CBFalconer wrote:
It doesn't, and adding it is a bad idea. There are times when you
deliberately want to hide an outer scoped identifier, and shadowing
it with a local one is the ideal method.

...
int important; /* critical to the rest of the system */
...
int mybiglongfunctionNOTusingimportant(params) {
....
int local;
int impossible;
...
important = whatever; /* absent minded typo for impossible */
...
}

The above will be perfectly legal coding, but buggy. The bug will
cause total implosion elsewhere. By simply relabelling impossible
as important we prevent such from ever occuring. Shadow good, bug
bad.

I don't get the comment. -Wshadow kicks in if you had "important"
as a local variable to the current nesting level. You don't so
that's not a shadowing diagnostic [one way or another].

I think he was trying to give an example where you *would* want to
use shadowing ie name the variable inside the function important
instead of impossible.

Exactly. It is somewhat analagous to the practice of putting the
constant first in an equality test to have the compiler help find
multilegged creatures:

if (123 == foo) ...

Yes, it's equally ugly. :cool:}
 
A

Andrew Poelstra

CBFalconer said:
(e-mail address removed) wrote:
CBFalconer wrote:

It doesn't, and adding it is a bad idea. There are times when you
deliberately want to hide an outer scoped identifier, and shadowing
it with a local one is the ideal method.

...
int important; /* critical to the rest of the system */
...
int mybiglongfunctionNOTusingimportant(params) {
....
int local;
int impossible;
...
important = whatever; /* absent minded typo for impossible */
...
}

The above will be perfectly legal coding, but buggy. The bug will
cause total implosion elsewhere. By simply relabelling impossible
as important we prevent such from ever occuring. Shadow good, bug
bad.

I don't get the comment. -Wshadow kicks in if you had "important"
as a local variable to the current nesting level. You don't so
that's not a shadowing diagnostic [one way or another].

I think he was trying to give an example where you *would* want to
use shadowing ie name the variable inside the function important
instead of impossible.

Exactly. It is somewhat analagous to the practice of putting the
constant first in an equality test to have the compiler help find
multilegged creatures:

if (123 == foo) ...

Yes, it's equally ugly. :cool:}

Not to mention that it can't fix confusion at statements like this:

if (x = printf ("%s", s))
{
/* If s isn't a null string, do this... */
}

It'll just make your coding style seem inconsistant.
 
B

Ben Pfaff

Andrew Poelstra said:
Not to mention that it can't fix confusion at statements like this:

if (x = printf ("%s", s))
{
/* If s isn't a null string, do this... */
}

I hope you don't actually write code like that. The following
is much more straightforward:

if (*s != '\0') {
fputs (s, stdout);
/* s isn't a null string, do something... */
}
 
G

Guest

Ben said:
I hope you don't actually write code like that. The following
is much more straightforward:

if (*s != '\0') {
fputs (s, stdout);
/* s isn't a null string, do something... */
}

And even if you must test with printf, it can be more clearly (in my
opinion) written as

if((x = printf("%s", s)) != 0) {
/* ... */
}
 
C

CBFalconer

Harald said:
And even if you must test with printf, it can be more clearly
(in my opinion) written as

if((x = printf("%s", s)) != 0) {
/* ... */
}

And everything is much less likely to crash with:

if (s && *s) {
fputs(s, stdout);
/* do something with non-empty string */
}
 
L

lovecreatesbeauty

Harald said:
And even if you must test with printf, it can be more clearly (in my
opinion) written as
if((x = printf("%s", s)) != 0) {
/* ... */
}

How about just as following in case of no need of one temporary:
if(printf("%s", s) != 0)
{
/* ... */
}
And everything is much less likely to crash with:
if (s && *s) {
fputs(s, stdout);
/* do something with non-empty string */
}

Why both of you are apt to check the argument of fputs and not like
other people to check the return value of printf? Even though the
argument (s, *s) is available, the function call can fail also, right?

I'm sorry if what I say offended one of you.

lovecreatesbeauty
 

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,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top