Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

- C has its own syntax for generics

- C has broader support for designated initializers

- C allows implicitly casting void* to any other pointer type

- C has fewer keywords, e.g. you can use "friend" or "class" as identifier

- ...

Despite all this, it's true enough that one can easily write C code that also compiles as C++.



sort by: page size:

C programmers use void pointers for generics. :)

I just want to point out that C actually supports generics in a form of pointer to void.

In C, because you often use void * for containers, there may be less code bloat than a container multiply used using generics which accessors are monomorphized for each type. In practice this is pretty trivial difference and can be bounded and understood well enough.

You'd have been right if you had said "C actually supports generics thanks to #define", but `void*` is the equivalent of interface{}

In some sense, you can do generic programming with C by using void*, but this throws out type safety.

C is weakly typed, because you can cast or set any variable to be a void *. Since C is weakly typed, then you can write a C++ program that is also weakly typed.

Both which ways? C was adopting C++ features before C90. Void type, function prototypes, scoped struct member tags.

Declaration syntax is not an impediment to safety or to static analyzers, except insofar as it is trickier to code a parser for them.


> It's one of C's main strengths that it allows abstract data types so easily.

On the contrary, data type abstraction in C is a pain. This was one of the reasons for creation of "C with classes" (a.k.a. C++).


void * is the C's equivalent of interface {} it has little to do with generics although it can be used to work around lack of it.

Perhaps there are other ways, but in C you have parametric polymorphism functionality through macros. That's why min() and max() are not functions but macros and they work with any type that can be compared, not just float64.


I don't quite follow. C will also prevent you from mixing up disparate pointer types; and c++ has no protection against void pointers.

> in C, generic code is usually implemented with the runtime overhead of void pointers or function pointers.*

When performance really matters, seasoned C programmers more often write task-specific implementations or choose macro-based libraries. In this particular benchmark, the C implementation is using a macro-based hash table which does not have the penalty of void*.


C has a generic: "void *". It just doesn't have any type safety.

C syntax is overall simple. The only syntax often confuses me is function typedef.

Static typing and C.

C is very simple and it's missing a Hindley-Milner type system.

If that was a part of it, I'd use it.

C++ wins now, every time. Type safety in C is a pain.


C has already added things not in C++, like _Generic.

C is full of implicit type conversions. I think the key is that C is based on value semantics and not references, and that makes pointers full-blown values with their own address, conversions, … - something closer to C's integer types than to other languages' references, and equally picky about operators.

Your information is very much out of date. C++ makes a few important changes that make most c code incompatible. #1, implicit cast between void and non-void pointers is not allowed, so something like:

    int *x = malloc(sizeof(int) * 15)
is legal c, but in c++ you would have to cast the malloc call. Also, type of character literals is int in c but char in c++. String literals are const only in c++. Functions that take no arguments must be declared as taking void (as in void func(void)) in c, but simply () in c++.

Then you could say that just using void-pointers in C that C is also dynamically typed.

The RAII benefits are definitely there and STL containers are pretty awesome, but you can still create generic containers in C by using void pointers. For example, a simple vector API:

  typedef struct { void *elements; int elem_size; int n; } Vector;

  Vector *vector_new(int elem_size);
  void vector_free(Vector *v);
  void vector_push(Vector *v, void *elem);
  void vector_pop(Vector *v);
  int vector_size(Vector *v);
  void *vector_at(Vector *v, int i);
etc. This is off the top of my head, but you get the idea. You can basically put anything you want in there as long as you say how large the elements are upon initialization.

There is a good book on generic C programming: http://sites.google.com/site/cinterfacesimplementations/

next

Legal | privacy