C or C++ do you prefer to program?

C or C++ do you prefer to program?

Post by Alan Coope » Tue, 15 Jul 2003 01:57:42

XXXX@XXXXX.COM writes in comp.unix.programmer:
|In which language do you prefer to program in
|a UNIX environment: C or C++?

Given that I am often working on code that should be portable to a
number of platforms, with a variety of compilers, and libraries that
should be callable from other peoples applications, compiled with a
variety of compilers, C is the only choice. Once all the C++ compilers
finish implementing the C++ standard and adopt a standard C++ ABI for
each platform, it might be usable. As long as every compiler implements
a different subset of the standard, and you can't link a library built
with one compiler with an application from another, it's useless to many

Of course, C++ is very useful to a large set of other people, with
different requirements and who don't care about the same constraints,
leading back to the m *** 'There is no one best tool for all jobs -
choose the hammer for the nail, and the screwdriver for the *** and
be happy you have both to use as necessary.'

Alan Coopersmith XXXX@XXXXX.COM
http://www.yqcomputer.com/ ~alanc/ aka: XXXX@XXXXX.COM
Working for, but definitely not speaking for, Sun Microsystems, Inc.

C or C++ do you prefer to program?

Post by Bjorn Rees » Tue, 15 Jul 2003 03:34:33

A function like strchr() really ought to be two overloaded functions:

char *strchr(char *s, int c);
const char *strchr(const char *s, int c);

However, C does not support function overloading, so the combination
of const and non-const in the current function signature is the best


C or C++ do you prefer to program?

Post by Peter Ammo » Tue, 15 Jul 2003 13:53:42

lewelly wrote:


That's right.

I disagree, at least for reference counting in general. With the C
libraries I use, they are also a performance optimization, because they
reduce the need to copy.

You could achieve the same results by copying a string every time you
increased its reference count. Using reference counting instead reduces
your memory useage and saves copying time.


This strikes me as utterly bizarre. Exactly what formatting does cout
<< "hello" have to do? Isn't ostream's << operator overloaded for
strings? Can't it determine at compile time that it's going to be
outputting a string? (printf() format strings, on the other hand, are
parsed at runtime.) The only overhead I can see is the necessity to
check for the zero character instead of knowing the length ahead of
time, and that's likely to be very small.

With cout, the formatting (or lack thereof) should be resolved at
compile time, especially for strings. With cout << 5, the compiler can
insert a jump to code to output an int; with printf("%d", 5), the
compiler typically doesn't.

Granted, like my cout << toupper('a') example.



C or C++ do you prefer to program?

Post by schul » Fri, 18 Jul 2003 05:30:48


I don't want to defend C++ - C is my choice for a number of reasons
(see below). However, there are few reasons why a well-written C++
program should be more than 5-10% slower than a well-written C
program. If you have such an extreme slowdown, the culprit is usually
an overloaded copy constructor that gets called at unexpected times.

However, the fact that this is frequent enough that I - not regular
C++ user by any means - have heard about it, makes it clear that C++
is full of pitfalls and traps.

And indeed, that is the major reason why I usually prefer C. It is a
fairly small language with a fairly obvious mapping to current
hardware. If you have the basic principles down, there is little to
surprise you. C is nearly a perfect match for its niche. And it gives
me enough tools to build nice abstractions (not as nice as Scheme or
Haskell, of course).

C++, on the other side, is a crawling abdomination from the deepest
pits of hell (TM). It's nearly as legible as Perl, while giving you
the full power of assembly language to shoot yourself into the
foot. It is to big, to unorthagonal, and much to ugly.

Finally, another advantage of C is the maturity of compilers and the
language. C is much more portable in practice.

What I am missing from C is some support for generic programming
(lists of foo, stacks of bar, ...). I usually follow the standard
library approach and hack something up with void*, but it is ugly and
breaks type checking.



-------------------------- It can be done! ---------------------------------
Please email me as XXXX@XXXXX.COM (Stephan Schulz)

C or C++ do you prefer to program?

Post by Sean Burk » Wed, 23 Jul 2003 06:17:08

XXXX@XXXXX.COM (Stephan Schulz) writes:

You can have strong type checking with only a little extra effort.
It turns out that you can generate type-safe wrappers for your
generic calls using the macro preprocessor. Below I've attached
the illustration of how to do it for a C list package, for those
who may be interested.


* Since these calls take void pointers, there is little type checking
* going on. If you wish to improve this, this package provides some
* macros that you can use to define a custom set of strongly-typed
* wrapper functions around the basic clist package. For example,
* say you wish to make lists to hold pointers to instances of foo_t:
* typedef struct { ... } foo_t;
* The macro below defines the prototypes for your wrapper functions.
* The first argument takes the place of 'clist' in the function names,
* the second defines the list type, and the last is the contained
* object type. The fourth argument can be 'static' or 'extern', to
* specify local or global linkage.
* CLIST_PROTOTYPES(foo, foo_list_t, foo_t, extern);
* The macro above creates the following definition:
* typedef struct foo_list_t_node
* {
* foo_t *first;
* foo_list_t_node *rest;
* } * foo_list_t;
* The CLIST_PROTOTYPES macro also creates a function prototype
* for each of the clist functions that is specialized for the
* foo_list_t, so the CLIST_PROTOTYPES macro invocation will
* generally be placed in a header file. For example, in place
* of clist_push() we define the function foo_push() with the
* prototype:
* extern void foo_push( foo_list_t *list, foo_t *data);
* The macro CLIST_WRAPPERS defines the actual wrapper functions,
* so the following invocation would go in one of the .c files:
* CLIST_WRAPPERS(foo, foo_list_t, foo_t, extern);
* This macro defines the wrapper for clist_push() as:
* extern void foo_push( foo_list_t *list, foo_t *data)
* {
* clist_push((clist_t *) list, (void *) node);
* }
* All of the other clist_*() functions are wrapped in similar fashion,
* Static linkage is preferred, as this will encourage your compiler
* to inline these functions, eliminating the wrapper function call.

The macros to define the wrapper prototypes and implementations
are defined like this:

/* Here is a package of macros to create strongly-typed
* wrappers for the clist calls. When these macros are
* instantiated, the user specifies substitutions for:
* root .. replaces "clist" in clist_push, clist_pop, etc.
* ltype .. list type, replaces clist_t
* dtype .. data type, replaces void
* For example, the macro below defines a list node whose `first'
* field points to the user's `dtype' data structure.
#define CLIST_NODE(ltype, dtype) \
typedef struct ltype##_node { \
dtype *first; \
struct ltype##_node *rest; \
} * ltype

/* Here is a custom prototype for the _push() function.
#define CLIST_PUSH_P(root, ltype, dtype) \
void root##_push(ltype *l, dtype *p)

/* And here is the custom wrapper for clist_push().
#define CLIST_PUSH(root, ltype, dtype) \
CLIST_PUSH_P (root, ltype, dtype) \
{ clist_push((clist_t *) l, p); }

[... define prototype and wrappers f