Re: C99 Question

From: Sidney Cadot (sidney_at_jigsaw.nl)
Date: 01/02/04

  • Next message: those who know me have no need of my name: "Re: C99 Question"
    Date: Fri, 02 Jan 2004 02:55:30 +0100
    
    

    Chris Torek wrote:

    >>... Most properly written C code compiles flawlessly in C++,
    >>except for a very small number of cases.

    > Either you have a different definition of "properly written" than
    > I do, or your experience differs quite a bit from mine. Using
    > gcc's "-x c++" to compile .c files as C++ code, I find that *most*
    > of the (C) code I deal with fails to compile -- yet, in most cases, it
    > seems "properly written" to me.

    In your experience, what are the most important reasons for this to fail?

    >>Lack of malloc() result casting is by far the most prominent
    >>cause for failure you would normally encounter.

    > This is just one of many errors that turns up.
    > But the diagnosed errors are not the ones that really worry me.
    > The scariest are the silent changes in semantics:

    Certainly.

    > % cat t.c
    > #include <stdio.h>
    >
    > struct A { char x[10]; };
    > int main(void) {
    > struct B { struct A { int i; } b1, b2; };
    >
    > printf("sizeof(struct A) = %lu\n", (unsigned long)sizeof(struct A));
    > return 0;
    > }
    > % cc -O -Wall -ansi -pedantic -o t t.c
    > % ./t
    > sizeof(struct A) = 4
    > % cc -x c++ -O -Wall -ansi -pedantic -o t t.c
    > % ./t
    > sizeof(struct A) = 10
    > %

    Ouch, that's messy.

    In all objectivity though: wouldn't you agree that most C programmers
    (even moderately able ones) would expect sizeof(struct A) to refer to
    the first definition? I know I would.

    To me, this example says: C has some pretty non-intuitive rules with
    regard to type resolution; avoid shadowing type names to avoid confusion.

    When I compile a C program as C++, I make a habit of also testing the
    resulting executable (the fact that one can do this is an advantage
    compared to lint). I would expect all my code to work in C++ as it does
    in C. If this fails for some reason, I am bound to learn something from it.

    In other words, I tend to constrain myself to the very large subset of C
    that's also C++ (which is surprisingly easy). Extra constraints are a
    good thing: that's why I prefer typed languages, am happy with C
    prototypes, and use very strict warning flags. In my limited experience,
    the C/C++-intersection language I use does not impose many strange
    demands on my C coding style (the malloc-cast, in practice, is the only
    one that I am consciously aware of), and it gives some benefits. The
    mileage of most here does seem to be worse than mine, although I suspect
    that some haven't even done the test drive :-)

    > (The above is just a boiled-down example, but we have had code like
    > it. The problem turned up when someone wanted to link C++ code
    > against an existing C library.)

    You must be glad you cought it. It's a nasty one.... It does not even
    qualify as a bug in C (it has perfectly well-defined semantics), but
    still it is best to avoid this type of thing altogether, I would say.

    Now for one question that I hesitate to ask: would you have cought this
    issue earlier on in your development cycle if you had done a C++ test
    compile & run every couple of weeks or so? (Perhaps that's not possible
    because your code is too "non-C++" for that to be an option).

    I prefer to do that once in a while on a Friday afternoon; the number of
    (potential) problems I catch in that way is small, but also non-zero.

    >>I guess what I am trying to say is that the issue is not as clear-cut as
    >>many here make it out to be. It sometimes looks like rehashing of
    >>arguments that were only relevant ten years ago.

    > Well, C99 does obviate the "omit the cast to obtain a diagnostic
    > if you somehow forgot <stdlib.h>" argument. But if you are using
    > C99, you might start using some of the new C++ features, which are
    > not exactly compatible with C++. C99's bool and complex types are
    > different, its new "restrict" keyword does not exist in C++, its
    > anonymous aggregate constructor syntax means something new, and so
    > on.

    Yes, there will be some divergence (although I suppose C++ compilers
    will start to support "restrict" sooner or later). For me, it's quite
    simple: as long as the benefits of having the ability to compile C
    programs with C++ programs outweigh the disadvantages, I'll keep on
    doing it. For now, it's a small enough price to pay (IMHO).

    Best regards,

       Sidney


  • Next message: those who know me have no need of my name: "Re: C99 Question"

    Relevant Pages

    • Re: Where does C++ fit in?
      ... code and compile it as C++. ... static constructors, memory allocation, exceptions). ... even there avoid stuff you don't need or can't afford. ... but watch out for static constructors if you're in the startup code. ...
      (comp.arch.embedded)
    • Re: Computer Shutsdown
      ... When I compile something big..kernel recompile, ... > Can anyone suggest me what do do, to avoid such shutdowns, Kernel ...
      (Fedora)
    • Re: What does this mean(Generics)
      ... What I find interesting about this example is that if you constrain T ... to be a “struct” then you will get a compile error. ... only permitted when comparing a value of a type supplied to a generic type ... then those overloads will be used. ...
      (microsoft.public.dotnet.languages.csharp)
    • Re: Definition in Header files
      ... way I can avoid doing this. ... I suggest you to use macro to define const-like value. ... be a compile time constant in C, ... for a double you have to use a macro or a global const variable. ...
      (comp.lang.c)
    • Re: novice: small annoyance
      ... is only required to declare a ... It might include no other headers. ... Indeed a good implementation might well avoid including ... to fail to compile. ...
      (alt.comp.lang.learn.c-cpp)