Book review (brief) 
Author Message
 Book review (brief)

This week I received a copy of a new book abouit C programming.
It is suitable for people who have had at least one semester of
instruction in C.

        C Interfaces and Implementations
        Teachniques for Creating Reusable Software
        David R. Hanson
        Addison-Wesley Professional Computing Series
        ISBN 0-201-=49841-3

There are a number of small slips, like spelling "disseminate" as
"disemminate" on the first page of the Preface and spelling "incidentally"
as "incidently" on p193

There are a lot of things I wouldn't do that way.
A number of things (like external identifiers that are not distinct
in the first 6 letters) are non-standard.
Quite a lot of things are perfectly splendid C, but will {*filter*}a C++
compiler.  (You thought C++ was a superset of C?  You were wrong.)
But it's a book about C, not C++.

However, if more C programmers read, understood, and imitated this book,
the world would be a better and safer place.  If you liked "Code Complete",
you'll probably like this book.

David Hanson and Christopher Fraser wrote "A Retargetable C Compiler:
Design and Implementation", which describes lcc, a compiler I am very
pleased to have.  David Hanson is a very good programmer, and most of
us will learn something useful from this book.

--
Australian citizen since 14 August 1996.  *Now* I can vote the xxxs out!
Richard A. O'Keefe; http://www.*-*-*.com/ %7Eok; RMIT Comp.Sci.



Tue, 09 Mar 1999 03:00:00 GMT  
 Book review (brief)


: Quite a lot of things are perfectly splendid C, but will {*filter*}a C++
: compiler.  (You thought C++ was a superset of C?  You were wrong.)

The only example I can think of, off the top of my head, involves
C comments containing "//". Are there many more interesting cases,
which are _not_ highly unlikely to occur in practice?

I was just about to post this, and thought of another one:
variable names in C which are C++ keywords, eg. "char private;".
Any more?

--
//.\\/\\/\\\\//////\//\/\/\/\\\/\\\/\\\\/\//\/\\\//\\\\/\\\//\/\\//\\\/\\//
\ Jason Tyler    .............  Brevity is  "Ha. Ha. Ha. Suckers!" pybpx- \

///\\/\\/\\\\\\/\\/\/\\/\\\/\//\\///\\\\\///\//\\\\\\\///\/\\\/\/\\\//\\//\



Fri, 12 Mar 1999 03:00:00 GMT  
 Book review (brief)

Quote:


>: Quite a lot of things are perfectly splendid C, but will {*filter*}a C++
>: compiler.  (You thought C++ was a superset of C?  You were wrong.)
>The only example I can think of, off the top of my head, involves
>C comments containing "//". Are there many more interesting cases,
>which are _not_ highly unlikely to occur in practice?

Yup.  The draft C++ standard has *pages* of them.  *Lots* of pages.
And I am not talking about the use of C++ constructs; I am talking
about pure standard conforming C code not being legal C++, or being
locally legal but meaning something else.

The two that are particularly noticeable in Hanson's book are

(1) typedef struct T *T;

    This is legal C.  Typedef names and struct tags live in completely
    different namespaces and can never conflict.  It is not legal C++;
    struct tags in C++ _are_ typedef names.

    /*problem1.c*/
    typedef struct T *T;
    struct T {int x;};

    int main() { T z = 0; return 0; }

    g% cc problem1.c
    g% CC problem1.c
    "problem1.c", line 2: Error: Multiple declaration for T.
    1 Error(s) detected.

    For many a year I have been a fan of "typedef struct Tag Tag;", even
    before C++.  This has the merit of being legal C _and_ legal C++ and
    having exactly the same outcome in both (Tag can be used as a struct
    tag and a typedef name).  I regard "typedef struct T *T;" as highly
    confusing and therefore bad practice in C.  However, when you *know*
    it is coming, you are not confused by it, and Hanson explains clearly
    what he's up to.    

(2) nested structs.

    /*problem2.c*/
    int main() {

        struct Foo {
            struct Bar {int x;} y;
            struct Ugh {int z;} w;
        };

        struct Bar p = {1};
        struct Ugh q = {2};

        struct Foo r;

        r.y = p;
        r.w = q;

        return 0;
    }

    This is legal C.  Struct braces do not count as block scopes for the
    purpose of deciding where the struct tag is visible.  This is not
    legal C++.  In C++ I would need to write

        Foo::Bar p = {1};
        Foo::Ugh q = {2};

    g% cc problem2.c
    g% CC problem2.c
    "problem2.c", line 9: Warning (Anachronism): Use "Foo(local)::" for access to Fo
    o::Bar.
    "problem2.c", line 9: Note: Type "CC -migration" for more on anachronisms.
    "problem2.c", line 10: Warning (Anachronism): Use "Foo(local)::" for access to F
    oo::Ugh.
    2 Warning(s) detected.

    Old C++ compilers treated nested structs the same as C, but this is one
    of the things that has changed in C++, and it changed a couple of years
    ago.  (The C++ ARM explains this.)  There is never any _need_ to have
    nested struct definitions in C, though it has always been legal and is
    often a natural enough way to proceed.

This does not count as a criticism of Hanson's book:  he never had the
intention of writing C++ code.  The code in the book is supposed to be
legal ANSI/ISO C.

As I said, if you thought C++ was a superset of C, think again.

--
Australian citizen since 14 August 1996.  *Now* I can vote the xxxs out!
Richard A. O'Keefe; http://www.*-*-*.com/ %7Eok; RMIT Comp.Sci.



Sat, 13 Mar 1999 03:00:00 GMT  
 Book review (brief)


Quote:

>The only example I can think of, off the top of my head, involves
>C comments containing "//". Are there many more interesting cases,
>which are _not_ highly unlikely to occur in practice?

        char *s = malloc(10);

which is *correct* in C, and not in C++.

There are more subtle ones; for instance, the behavior of
        'abcd'
is implementation defined in C, but I don't know what C++ does, since in
C++, 'a' is a char, not an int.

-s
--

Unix/C Wizard - send mail for help, or send money for consulting!
The *other* C FAQ, the hacker FAQ, et al.  See web page above.
Unsolicited email (junk mail and ads) is unwelcome, and will be billed for.



Sat, 13 Mar 1999 03:00:00 GMT  
 Book review (brief)

Quote:


> : Quite a lot of things are perfectly splendid C, but will {*filter*}a C++
> : compiler.  (You thought C++ was a superset of C?  You were wrong.)

> The only example I can think of, off the top of my head, involves
> C comments containing "//". Are there many more interesting cases,
> which are _not_ highly unlikely to occur in practice?

> I was just about to post this, and thought of another one:
> variable names in C which are C++ keywords, eg. "char private;".
> Any more?

Some of these are pretty unlikely, but the first certainly is not.

        #include <stdlib>
        ...
        int* a = malloc(10 * sizeof(int));  /* needs cast in C++ */

        extern void f();
        ...
        f(1);   /* undeclared function in C++ */

        double sin(double);  /* must include <math.h> in C++ rather */
                             /* than supplying own declaration */

        int var__x; /* var__x reserved in C++ */

        goto foo; /* cannot jump around initialized variable in C++ */
        {
          int i = 0;
          ...
        foo:
          i = 1;
        }

Michael M Rubenstein



Mon, 15 Mar 1999 03:00:00 GMT  
 Book review (brief)

Quote:

>The only example I can think of, off the top of my head, involves
>C comments containing "//". Are there many more interesting cases,
>which are _not_ highly unlikely to occur in practice?

>I was just about to post this, and thought of another one:
>variable names in C which are C++ keywords, eg. "char private;".
>Any more?
>--
>//.\\/\\/\\\\//////\//\/\/\/\\\/\\\/\\\\/\//\/\\\//\\\\/\\\//\/\\//\\\/\\//
>\ Jason Tyler    .............  Brevity is  "Ha. Ha. Ha. Suckers!" pybpx- \

>///\\/\\/\\\\\\/\\/\/\\/\\\/\//\\///\\\\\///\//\\\\\\\///\/\\\/\/\\\//\\//\

1.
char hello[5] = "Hello";

2.
#include <stdlib.h>
int *ptr = malloc(5 * sizeof(int));

[ C++ requires explicit type conversion (int*)malloc(); ]

3.
in C, main can be called recursively.  (This isn't common but it is
legal, I had occasion to use it once.  I'm not absolutely certain,
but I believe this is according to the current C standard.)

--
Roger Wells (speaking only for myself)



Mon, 15 Mar 1999 03:00:00 GMT  
 Book review (brief)

re legal C that is not legal C++ or not the same in C++ :

a couple more I realized, that I haven't seen mentioned yet:
C:  'a' is type int  C++: 'a' is type char

This is important in C++, otherwise (assuming ASCII)
cout << 'a'  could not be distinguished from  cout << 0x61

The only place I can see that this would change a legal C program would
be the use of sizeof('a'), which is not a likely construct.

Still legal in C but no longer advised:

double fct3();

int fct1(int a)
{
        double x = fct3(a);
        if (fct2(x))
                return 1;
        return 0;

Quote:
}

in C:   fct3 declared as returning double with no information about
its parameter list; consistant with use
        fct2 defaults to type int with no information about its parameter
list; consistant with use

In C++: fct3 declared as taking no arguments and returning double,
conflicts with use
        fct2 missing prototype

--
Roger Wells (speaking only for myself)



Mon, 15 Mar 1999 03:00:00 GMT  
 Book review (brief)


|> : Quite a lot of things are perfectly splendid C, but will {*filter*}a C++
|> : compiler.  (You thought C++ was a superset of C?  You were wrong.)
|>
|> The only example I can think of, off the top of my head, involves
|> C comments containing "//". Are there many more interesting cases,
|> which are _not_ highly unlikely to occur in practice?
|>
|> I was just about to post this, and thought of another one:
|> variable names in C which are C++ keywords, eg. "char private;".
|> Any more?

extern int f();

means quite different things in C and C++.  This construct has been a
problem in every C program of significant size that I've tried
to jam through a C++ compiler.  (Yes, of course you can and should avoid
the problem by using prototypes.  Few people are perfect about that unless
the compiler tells you when you omit one.)



Mon, 15 Mar 1999 03:00:00 GMT  
 Book review (brief)

    Roger> a couple more I realized, that I haven't seen mentioned
    Roger> yet: C: 'a' is type int C++: 'a' is type char

    Roger> This is important in C++, otherwise (assuming ASCII) cout
    Roger> << 'a' could not be distinguished from cout << 0x61

    Roger> The only place I can see that this would change a legal C
    Roger> program would be the use of sizeof('a'), which is not a
    Roger> likely construct.

Here is a snippet of my code which relies on 'a' being int.  It also
uses an extension of multiple characters in a constant which raises a
compiler warning while I am editing.  The purpose of the code is to be
able to embed the numerical SCCS version number in a program.  While
the program is being edited the version is set to 0.

#define MY_VER_NO (%R%U)

/* kludge to allow build while this file is out for edit */
#if '%R%' == 0x255225
#   undef  MY_VER_NO
#   define MY_VER_NO (0U)
#endif

Of course this kludge is only because I want the preprocessor to do
the work.  I could have used a runtime strtoul("%R%", 0, 10).
--
Pete Forman
Western Geophysical



Tue, 16 Mar 1999 03:00:00 GMT  
 Book review (brief)

One other that no one's yet mentioned is the scoping of consts. In C,
they're global, in C++, they're local. Also, in C++ a const is not
necessarily an lvalue, e.g.

----[ File.C]----

const int a = 1;           /* Global lvalue     */
static const int b = 2;    /* File scope lvalue */

----[ File.Cpp]----

const int a = 1;           /* File scope non-lvalue */
extern const int b = 2;    /* Global non-lvalue     */

----[ finis ]----

Consts in C++ are treated almost exactly like #defines in C.



Wed, 17 Mar 1999 03:00:00 GMT  
 Book review (brief)

Quote:

> One other that no one's yet mentioned is the scoping of consts. In C,
> they're global, in C++, they're local. Also, in C++ a const is not
> necessarily an lvalue, e.g.

> ----[ File.C]----

> const int a = 1;           /* Global lvalue     */
> static const int b = 2;    /* File scope lvalue */

> ----[ File.Cpp]----

> const int a = 1;           /* File scope non-lvalue */
> extern const int b = 2;    /* Global non-lvalue     */

> ----[ finis ]----

> Consts in C++ are treated almost exactly like #defines in C.

Also, consts in C++ are treated almost exactly like consts in C :-)

Aside from the difference in default linkage, a C++ const still is
still an lvalue and may be used where an lvalue is required, except
that it may not be changed.  For example, you may take the address of
a const object in either language.

Also, in either language you may declare

        extern const int b;

b must be defined elsewhere.  If a const is declared extern without an
initializer in C++ it does not have the semantics of a constant
expression -- it behaves just like a C const.

Michael M Rubenstein



Fri, 19 Mar 1999 03:00:00 GMT  
 Book review (brief)


 >
 >> One other that no one's yet mentioned is the scoping of consts. In C,
 >> they're global, in C++, they're local. Also, in C++ a const is not
 >> necessarily an lvalue...
 >>
 >> Consts in C++ are treated almost exactly like #defines in C.
 >
 >Also, consts in C++ are treated almost exactly like consts in C :-)
 >
 >Aside from the difference in default linkage, a C++ const still is
 >still an lvalue and may be used where an lvalue is required, except
 >that it may not be changed.  For example, you may take the address of
 >a const object in either language.

That's what I meant when I said that a C++ const isn't *necessarily* an
lvalue. If you take its address, the compiler will assign storage to it.
However, if you reference it only by value, a quick check of the link map
will reveal that it has no storage, just like a #define'd constant. This is
true of most C++ compilers.

 >If a const is declared extern without an
 >initializer in C++ it does not have the semantics of a constant
 >expression -- it behaves just like a C const.

True.



Fri, 19 Mar 1999 03:00:00 GMT  
 Book review (brief)

Quote:



>  >> One other that no one's yet mentioned is the scoping of consts. In C,
>  >> they're global, in C++, they're local. Also, in C++ a const is not
>  >> necessarily an lvalue...

>  >> Consts in C++ are treated almost exactly like #defines in C.

>  >Also, consts in C++ are treated almost exactly like consts in C :-)

>  >Aside from the difference in default linkage, a C++ const still is
>  >still an lvalue and may be used where an lvalue is required, except
>  >that it may not be changed.  For example, you may take the address of
>  >a const object in either language.

> That's what I meant when I said that a C++ const isn't *necessarily* an
> lvalue. If you take its address, the compiler will assign storage to it.
> However, if you reference it only by value, a quick check of the link map
> will reveal that it has no storage, just like a #define'd constant. This is
> true of most C++ compilers.

So what does this have to do with lvalue-ness?  I imagine that if I
declare a static const in C, and never take its address, the compiler
will not assign storage to it, and you won't find it in the link map
either.  This is a perfectly valid optimization (because of the as is
rule) in either language.

There is a significant difference between const int in C and in C++,
although it won't affect trying to compile a C program as C++.  In C++,
an initialized const with integral type can enter into a constant
expression, thus:

                int const n = 10 ;
                char a[ n ] ;        /* legal in C++, illegal in C */

FWIW: the major difference between a const int and a #define, in both
languages, is that the const int will obey scope rules, whereas the
#define won't.  A perhaps even more important difference is that a const
int is always a constant integral value, whereas a #define can be
anything, even something which changes program syntax.

--

GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle --
                            -- Beratung in industrieller Datenverarbeitung



Tue, 23 Mar 1999 03:00:00 GMT  
 Book review (brief)


[snip]

Quote:
>There is a significant difference between const int in C and in C++,
>although it won't affect trying to compile a C program as C++.  In C++,
>an initialized const with integral type can enter into a constant
>expression, thus:

>            int const n = 10 ;
>            char a[ n ] ;        /* legal in C++, illegal in C */

My impression is that this is not illegal in C (though certainly
it is not portable in any sense).  I'm translating "illegal" here
to "requires a diagnostic" which I don't think this does.

X3.159-1989, section 3.4, near the end:
        "An implementation may accept other forms of constant
        expressions."

Cheers,
Stan.
--



Thu, 25 Mar 1999 03:00:00 GMT  
 
 [ 16 post ]  Go to page: [1] [2]

 Relevant Pages 

1. technical review opportunity on managed C++ programming book...

2. Seeking Book Review - C# Design Patterns

3. Book review: "C Interfaces and Implementations"

4. Book Review

5. C book review request

6. Book review?

7. The Computer Book Review - FREE COPY!

8. C books reviews

9. Book-reviews

10. Platt, Rogerson, Thorpe, MS, Mowbray Component Book Reviews

11. REVIEW: The C and C++ Review prerelease version

12. For loop design ( Brief Lesson )

 

 
Powered by phpBB® Forum Software