osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Lies in education [was Re: The "loop and a half"]


On Thu, Oct 12, 2017 at 2:43 AM, Marko Rauhamaa <marko at pacujo.net> wrote:
> Chris Angelico <rosuav at gmail.com>:
>
>> The places where C++ is not a superset of C are mostly things you
>> wouldn't want to be doing anyway. You can generally take C code and
>> compile it with a C++ compiler, and it'll have the same semantics.
>
> Here's a C/C++ program:
>
> ========================================================================
> #include <stdio.h>
>
> int main()
> {
>     struct {} s;
>     printf("%d\n", (int) sizeof 'a');
>     printf("%d\n", (int) sizeof s);
>     return 0;
> }
> ========================================================================
>
> When compiled (with gcc) as a C program, the output is:
>
>     4
>     0
>
> When the same program is compiled (with gcc) as a C++ program, the
> output is:
>
>     1
>     1
>
> That is not immediately all that significant but points to subtle
> incompatibilities between the data models of C and C++.

Indeed - their handling of empty structs is different. But that
doesn't invalidate my point; how often do you declare a variable that
has nothing in it? Remember, a Python object with no attributes still
has an identity, a type, and so on; in C, data has no type or
identity, so this truly has no data attributes. This is legal but
extremely esoteric, and the difference in sizeof is less about an
incompatible data model and more about the definition of an empty
struct.

> Then we have syntactic problems:
>
> ========================================================================
> int main()
> {
>     void *s = "hello";
>     char *t = s;
>     return 0;
> }
> ========================================================================
>
> which, as a C program, makes gcc perfectly happy, but a C++ compilation
> complains:
>
>    test.C: In function ?int main()?:
>    test.C:5:15: error: invalid conversion from ?const void*? to ?void*? \
>    [-fpermissive]
>         void *s = "hello";
>                   ^~~~~~~
>    test.C:6:15: error: invalid conversion from ?void*? to ?char*? [-fper\
>    missive]
>         char *t = s;
>                   ^
>
> (The first one should trigger an error message even in C compilation,
> but string literals were standardized to be "semiconstant" in C.)

Also something you should not be using. For hysterical raisins,
certain things in C are legal-yet-highly-inadvisable, and one of them
is putting string literals into non-const pointers. (C didn't
originally even _have_ const.) You'll probably find that some
compilers give a warning (at least if -Wall is active), but even if
not, you shouldn't be doing this.

So I stand by my original statement. Yes, there are incompatibilities,
but it's easy enough to write code that's compatible with both. Hmm,
something tells me I've heard this sort of thing before...

ChrisA