C/C++ guidelines

T

Tor Rustad

Keith said:
Consider programming in C90 and making sure not to accidentally use a
C++ compiler. You can enforce this with:

#ifdef __cplusplus
#error "Use a C compiler, not a C++ compiler"
#endif

That was a bit drastic, the code should compile under both C and C++,
and a C compiler will not detect if reserved C++ keywords are used. To
test this, a C++ compilation is rather useful. IMO, this is better:

#ifndef __STDC__
#warning "Non Standard C compiler used"
#endif

above, can be extended to detect C95 and C99, via __STDC_VERSION__ checks.

For C++ compilation, the C header files need this:

#ifdef __cplusplus
extern "C" {
#endif

...bla. bla...

#ifdef __cplusplus
}
#endif
 
T

Tor Rustad

Robbie said:
Hi groups,

I'm about to embark on a new project and for maximum portability we've
been asked to code it in the common subset of C and C++.

Can anyone suggest any good documents that might help us? Lists of
gotchas to avoid, that sort of thing?

See

H&S: "C Reference Manual", 5th ed.

which not only addresses the differences between C89, C95 and C99, but
also the subset of Standard C and Standard C++.
 
K

Keith Thompson

Chris Hills said:
Firstly what are the compilers and targets?

Due to the lack of serious take up of the current C99 standard and
many compiler having compiler and target extensions (also domain
extensions) it is better to start with the tools than the standard.

You have asked a practical not theoretical question.

But the C90 standard, even though it's "officially" obsolete, is
almost universally supported. If you write C90-conforming code with
no extensions, and manage to avoid exceeding implementation-defined
limits, you can be reasonably confident that your code will compile
and run with any existing compiler invoked with appropriate options.

For maximal portability, you can stick to the intersection of C90 and
C99. This means avoiding implicit int and implicit function
declarations, avoiding C99 keywords, and probably a few other things.

If you really need your code to be compatible with C++ as well, the
main things to worry about are avoiding C++ keywords, dealing with the
lack of implicit conversions to and from void*, and probably some
other things I haven't thought of.

But there are other subtle differences between C and C++, and if
you're going to write code that compiles as both, you'll *always* have
to worry about the possibility of running into one of them.

As I mentioned elsethread, you should consider just programming in C.
I've never heard of a platform that has a C++ implementation but not a
C implementation.
 
F

Flash Gordon

Army1987 wrote, On 16/09/07 16:25:
There is code which is well formed in both C90 and C99 which will
do different things in the two versions of the language,

The only one I can think of likely to do that is very much a corner
case. I can think of things which will produce a diagnostic in one but
not the other, but that is a different matter.
but I've
never heard anyone suggesting *not* to try to write code in their
common subset.

You haven't been reading this group carefully enough for the last few
years. I've certainly seen people advocating the use of things
introduced by C99, and I know someone not on this group who would still
be using implicit int despite C99 if I had not forced it on him.

However, the common subset of C90 and C99 is a very different matter
since they are versions of the same language rather than being different
languages.
 
L

LR

Robbie said:
Hi groups,

I'm about to embark on a new project and for maximum portability we've
been asked to code it in the common subset of C and C++.

This seems like a bad idea predicated on a false assumption. I suspect
that trying what you're being asked for is unlikely to be productive and
may not be possible.

Can anyone suggest any good documents that might help us? Lists of
gotchas to avoid, that sort of thing?

I don't know.

What I can suggest is that you take a completely different tack on the
problem. I think looking here http://www.comeaucomputing.com/ might
help you accomplish your goal of maximum portability, although of
course, you may have to be more specific as you what you mean by
portability.

You may also wish to google for retargetable compilers.

If you are able, could you please let us know what was finally decided
and how it worked out?

TIA.

LR
 
K

Keith Thompson

Richard said:
What strange advice.

Not at all.

C on a given OS and C++ on the same OS can be treated as two different
platforms. If you want your code to be valid C and valid C++, with
the same semantics in both languages, regularly testing it in both
languages can be extremely helpful. For example, if you accidentally
use 'class' as an identifier, the error will be caught almost
immediately in testing. If you write code that depends on the value
of sizeof 'a', testing is likely to catch the error (if the tests are
good enough).

If you have a requirement to support two different operating systems,
you do your testing on both. If you have a requirement to support two
different languages, you do your testing on both. The same, or very
similar, techniques are applicable.
 
J

James Kanze

For maximum portability, write unit tests for all your code.
Then you can run the tests on each target platform.

There's a bit of truth there, in that the only really portable
programs are those that have been ported. Still, it won't help
you up front, if the requirements are that the code work on a
machine you don't yet have access to. While nothing can
absolutely guarantee that (not even running the tests when you
finally get access---tests can prove that the code doesn't work,
but never that it does), knowing things that typically cause
portability problems, and avoiding them, can increase your
chances of not having too many problems in a port.
For _real_ portability (not just "tell our boss we are
portable" portability), you could configure a test server on
each target platform. Run the test suite each time you
integrate, automatically on each platform. Configure them to
e-mail all the developers if the tests break on any platform.

Which is fine (and definitely should be done) for the platforms
you have access to today. It doesn't help for those that you
might encounter in the future.
 
J

James Kanze

And it is execreble dangerous coding in C.

It's what Brian Kernighan recommended, at least according to
people who worked with him. (But this was before the ISO
standard, void* and what all else. I wouldn't say "execreble",
but I'd normally leave the cast out in C too.)
The languages are
different. This is c.l.c, and c.l.c++ is a separate newsgroup
dealing with a separate language. F'ups set.

The problem is that the original poster wanted to use a common
subset of the two languages. Now, this may not make much sense
to you (or to me---I can see doing it in a few shared headers,
but not in any implementation files), but that's what he asked
for.
 
K

Keith Thompson

Jerry Coffin said:
The first thing you should do is talk to your management about setting
goals that are realistic, meaningful and useful. For truly maximum
portability, you should restrict yourself to a fairly small subset of C
with no floating point, etc. (e.g. a talking greeting card doesn't
generally include floating point hardware, and neither will a rad-hard
80286 for use in a satellite).

If the code is intended for embedded systems and/or freestanding
implementations, restrictions like avoiding floating-point can make
sense. If it's intended to run on hosted systems, such as
workstations or servers, then you can safely assume that
floating-point is going to be available and reasonably fast.

We tend to assume here in comp.lang.c that most questions we get are
about hosted implementations, unless the questioner explicitly says
otherwise. That's usually a valid assumption; it's been plausibly
claimed that most C programming is done for embedded systems, but most
people learning C use hosted implementations (commonly Windows or
something Unix-like).
A practical goal should be measureable, and should carry a measurable
benefit, that outweights the cost. "Maximum portability" isn't
measureable, carries no measurable benefit, and the cost is extreme.

The cost of writing most of your code in the intersection of C90 and
C99 is minimal, and it's good practice anyway (unless you're willing
to limit yourself to implementations that support some or all of the
new C99 features).
Right now, I think the cart has been placed squarely in front of the
horse -- the decision to restrict the language has been made with what
is clearly insufficient analysis or reason. Only after meaningful goal
has been set will it be possible to make such a decision -- and with a
meaningful goal in mind, the decision will most likely change as well.

You may be right, but I don't think we have enough information to
assume that. The OP's single sentence didn't tell us how much thought
went into setting the requirement.

To the original poster: Can you tell us more about what went into the
decision to use the common subset of C and C++?
 
R

Richard

Keith Thompson said:
Not at all.

Yes. he is explaining how to QA the system. And not in detail. The
advice being sought is the subset with which to create the system.
C on a given OS and C++ on the same OS can be treated as two different
platforms. If you want your code to be valid C and valid C++, with
the same semantics in both languages, regularly testing it in both
languages can be extremely helpful. For example, if you accidentally

Of course. And I never suggested otherwise. But that could be said about
simply *any* software.
use 'class' as an identifier, the error will be caught almost
immediately in testing. If you write code that depends on the value
of sizeof 'a', testing is likely to catch the error (if the tests are
good enough).

Yes, It's called testing.
If you have a requirement to support two different operating systems,
you do your testing on both. If you have a requirement to support two
different languages, you do your testing on both. The same, or very
similar, techniques are applicable.

Yes. Of course. But this is not the issue. Any programmer knows to test
his code regularly *especially* in a set up like this. But high level
"test your code" advice is not exactly apt and could, if I wanted to be
pedantic, called "Off Topic".

A parallel might be someone asking

"can I use int values to hold floats using cast" and the answer comes
back as "test it regularly".
 
P

Phlip

Jerry said:
A practical goal should be measureable, and should carry a measurable
benefit, that outweights the cost. "Maximum portability" isn't
measureable, carries no measurable benefit, and the cost is extreme.

Thanks that was awesomely correct.

Now notice how my advice - actually become demonstrably portable as early as
your first lines of code - was essentially the same.

Crew: Can we have a Sharp Zaurus to run our unit tests on
early and often?

Boss: No!

Crew: Okay; you don't mean obsessively portable, you just
mean generally portable. Gotcha!
 
P

Phlip

Richard said:
A makefile does nothing to make the code a working cross section which
is valid C and C++. Which is what the OP asked for.

I have not done what the OP asked for, and I didn't say I did.
 
R

Richard

Phlip said:
I have not done what the OP asked for, and I didn't say I did.

I know. And I pointed this out. Which begs the question, what were you
saying other than "test the sw"?
 
M

Mark McIntyre

At least lcc-win32 DOES warn you: "Missing prototype for 'malloc'.

It may, but its not obliged to. I prefer not to rely on optional
warnings which may vanish between compilers, or between different
versions of the same compiler
Moreover: From the answer in the FAQ I deduce that the claim
is simply wrong: It's not the usage of the cast (as such) which "might
introduce subtle errors.


There's another, more subtle, error which you've failed to notice.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
G

Guest

There is code which is well formed in both C90 and C99 which will
do different things in the two versions of the language, but I've
never heard anyone suggesting *not* to try to write code in their
common subset.

Nor is there a good reason to do so, since the common subset is a
"lesser" C, why not not just write C instead. The common subset does not
have any of the "additions" that C++ brings (objects, templates, etc.)
and it does not even have all of C, so what is the gain of using the
common subset? The only thing you gain is the headache of avoiding those
cases where the semantics differ.
 
M

Mark McIntyre

Actually, I already found that habit (casting malloc's return value)
described as _good coding practice_.

Then either you were reading a C++ book, or you were reading pulp
fiction.

You should only cast when you actually need to, and you should make
sure you really understand why.

This is not one of those cases and all you're doing is cluttering up
your code.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
M

Mark McIntyre

[...] in C you should not cast the result of malloc, because
doing that might introduce subtle errors [...]

For example?
Failure to #include <stdlib.h> going undetected.
Huh?

So it's _not_ the usage of the cast (as such) which "might introduce
subtle errors" but forgetting to include <stdlib.h>.

Splitting hairs. If the cast were not there, you'd be warned about the
missing prototype. By inserting the cast, you mask the other error.
On the other hand most modern C compilers (as it seems) would catch
that lapse (and produce a warning).

Its a warning and (in C89 at least) no diagnosis is actually required.
So you're relying on Quality of Implementation.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
R

Richard Tobin

On the other hand most modern C compilers (as it seems) would catch
that lapse (and produce a warning).
[/QUOTE]
Its a warning and (in C89 at least) no diagnosis is actually required.
So you're relying on Quality of Implementation.

*You* rely on that all the time. The fact that your compiler doesn't
print "Congratulations! Out of cheese!" when you write a*_=6^%7q++*;
is thanks merely to quality of implementation.

-- Richard
 
P

Phlip

Richard said:
I know. And I pointed this out. Which begs the question, what were you
saying other than "test the sw"?

I want to be able to rapidly add features and refactor my code with freedom
to not manually test all its requirements after each tiny change.

I want tiny changes, so I can make sure each one returns to a fully running
project. Lots of small tested changes are always safer than many big changes
between tests.

If one of the requirements is portability between platforms X and Y, I want
both platforms to experience each test run. I want this at the level of 1~10
edits between change. I edit, hit my editor's test button, and wait for a
beep. When I get it, I keep editing. This technique permits me to make the
narrowest possible changes, testing as frequently as possible.

Note this implies the requirement is "portability between platforms X and
Y". If the requirement is, instead, "port to some platform that the boss
might someday need", I must reject the requirement as untestable. Whoever
required that is responsible for picking platforms X and Y, now, or dropping
this silly requirement.
 
P

Phlip

Richard said:
Yes. he is explaining how to QA the system.

A> developers should write and run tests as they write code. That's not QA.

B> portability _is_ QA. Without tests saying you hit your platforms,
you have only vaporware.

But, like Kanze pointed out, the question doesn't make much sense, and I
doubt we will hear back from the original poster to clarify...
 

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

Latest Threads

Top