On 01/12/2011 04:52 PM, sandeep wrote:
...
In my opinion, compatibility with C++ is one of C's greatest assets. I
recommend the ISO C body to move towards these two goals viz-a-viz C++:
1. any program that is syntactically valid both in C and C++, should have
the same semantics in both languages
This program contains two modules and one shared header. It's very
carefully designed to make many different points in a program that is as
small as possible. I make no claim that this represents good programming
practice:
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;
}
Both modules contain syntactically valid code: according to C99, C++98,
and C++03, together they constitute strictly conforming C code, and
well-formed C++ code. The behavior of code containing __cplusplus is
technically undefined under C90, but for most (all?) fully conforming
C90 compilers, the behavior is exactly as if it were not a reserved
identifier, and not a pre-#defined macro. For any such C90 compiler, the
only code that would otherwise constitute a syntax error will be dropped
by the #if's.
You can compile both modules in C, or both in C++; the resulting
executables are guaranteed by the relevant standards to exit with a
failure status, for quite different reasons in each case. If you compile
the first module in C, and the second in C++, and the two compilers are
compatible, then the modules can be linked together; in that case, the
executable will exit with success status. Unfortunately, if you do it
the other way around, they cannot be linked.
Why does it matter which language is used for each module? Because three
of the comparison operators are guaranteed to have a different value,
depending upon whether the module is compiled as C or C++. The other two
comparisons will have the same value in both languages only in the
unlikely event that sizeof(int)==1. I'll leave it as an exercise for the
reader to figure out why these statements are true.
Please note that, while this code is VERY contrived, it depends upon
very deep principles of the two languages. For every single comparison
operator in the above code, guaranteeing that it would be true in both
languages would break a lot of code in one of the two languages.
So, if you want the semantics of this program to be the same in both
languages, what should they be?