On 05/19/2013 05:35 AM, Bart van Ingen Schenau wrote:
....
There are a few less used, darker corners of C and C++, where a C and a C+
+ compiler silently give different results. The most notable is the type
of character literals (and consequently, the result of sizeof on them):
#include <stdio.h>
int main()
{
if (sizeof(char) == sizeof(int))
puts("Can't tell. char and int have same size");
else if (sizeof('a') == 1)
puts("C++");
else
puts("C");
return 0;
}
This is the only silent difference between C and C++ that I am aware of.
There's a few others.
If there are any others, they will likely affect you even less than this
one.
You're probably right about that.
On course, there are also some C constructs that are not valid in C++
(e.g. implicit conversion from void* to T*), but of those the compiler
will complain loudly enough.
I've posted versions of the following material three times, most
recently in a message dated 2011-06-19. It has never provoked much
discussion, which disappointed me. I haven't updated it for the most
recent versions of the C and C++ standards, but I doubt that it needs
modification for either one.
The following is very carefully designed to make many different points
in a program that is as small as possible. I make no claim that it is an
example of good programming practice
It is syntactically valid code in both C and C++, conforms strictly to
the C99 standard, and is well-formed code according to both the C++98
and C++03 standards. It's behavior under C90 is technically undefined,
but only by reason of it's use of __cplusplus, an identifier which a C90
compiler could, in principle, have reserved for it's own incompatible
usage - but such compilers are rare, and probably non-existent.
You can compile and link both modules as C code, or as C++ code; the
resulting executables are guaranteed by the applicable standards to exit
with an failure status, for two entirely different sets of reasons,
depending upon which language is used (note that many compilers
automatically infer the language to be used from the extension on the
filename - you might need to rename the files to get them to actually
compile in one language rather than the other).
If you compile the first module with C, and the second with C++, it is
guaranteed to return a successful exit status. If C++ were really just
an extension to C, then what I've said about how this program's behavior
varies with the programming language would be impossible.
shared.h:
=========
#ifndef SHARED_H
#define SHARED_H
extern char tag;
extern int enumer[2];
typedef void voidvoid(void);
int Cnmtyp(void);
int Cfunc(voidvoid*);
#endif
First module:
=============
#ifdef __cplusplus
extern "C" {
#endif
#include "shared.h"
char tag = 0;
static int hidden(voidvoid *pfunc)
{
(*pfunc)();
tag = sizeof 'C' == sizeof(int);
return Cnmtyp() && enumer[0] && enumer[1];
}
int Cfunc(voidvoid* pfunc)
{
struct tag
{
enum { enumer, other } in;
int integer;
} out;
out.integer = sizeof(tag) == 1 && sizeof(enumer) == sizeof out.in;
return hidden(pfunc) && out.integer;
}
#ifdef __cplusplus
}
#endif
Second module:
==============
#ifdef __cplusplus
extern "C" {
#endif
#include "shared.h"
int enumer[2] = {0, 1};
static void Cppname_Cpptype(void)
{
enumer[0] = sizeof 'C' == 1;
return;
}
#ifdef __cplusplus
}
#endif
int Cnmtyp(void)
{
struct tag
{
enum { enumer, other } in;
int integer;
} out;
out.integer = sizeof(enumer) == 2 * sizeof(int);
return out.integer && sizeof(tag) == sizeof out;
}
static voidvoid Cppname_Ctype;
static void Cppname_Ctype(void) {
Cppname_Cpptype();
}
int main(void) {
return Cfunc(&Cppname_Ctype) && tag;
}
As an exercise for the student: explain precisely why three different
conditional expressions in the above code are guaranteed to have
different values in C and C++, and why two other conditionals will have
different values except in the unlikely case that sizeof(int)==1.