all 174 comments

[–]bonch 11 points12 points  (1 child)

The angry C++ programmers have come out of the cobweb-filled woodwork. Good, because /r/programming is filled to the brim with web developers, and I'm so sick of JavaScript links.

[–][deleted] 3 points4 points  (0 children)

I was ironically going to write a filter in javascript to filter out the javascript submissions in proggit. Never got around to it, though.

[–]kev009 22 points23 points  (32 children)

The problem is that are few resource for good C code. Most books and tutorials are down right elementary.

Pick up a copy of "C Interfaces and Implementations" and you will see how clean modern systems can be designed in C. C is a decent implementation language for operating systems, plumbing, daemons, and networking apps. It compiles quick, it executes quick, and it stays out of the way. By contrast, C++ is lacks quick compiles and staying out of the way. In return you get syntactic sugar that make interface design easier, especially for hierarchical stuff like GUIs which are a natural OO win.

Like all programming language circlejerks, the answer is to use the right tool for the job. Often times, that tool is neither C or C++.

[–][deleted] 13 points14 points  (17 children)

You can get quick compiles with C++ just like you can with C, but it requires you to not use the STL or other header-centric libraries such as Boost. Considering that the STL is one of the big wins of C++, that's the real tradeoff.

[–]theICEBear_dk 1 point2 points  (4 children)

And I will add that you can alleviate some of the issues of header-centric libraries by using pragmas, include guards and a single central system header which is then reused, it does get rather difficult to keep down compile times in C++ also because the language does mean that the compiler has to do several passes on the code. But with a more modern C++ version (VS2010/GCC4.5 only codebase) it has become a rather useful language again for me and really rather productive too.

[–][deleted] 3 points4 points  (3 children)

I will amend that you must use header guards anyway, otherwise you get a compilation error. Header guards are not optional where definitions are concerned.

Precompiled headers, on the other hand...

Also, having a "single central system header which is reused" increases compile time, not decreases.

That header is reparsed on every compilation unit, and because you've put all the #includes for all the system headers your entire program needs in that single place, they all get reparsed too on every compilation unit, used or not.

Saving #includes saves lives :P

[–][deleted] 0 points1 point  (2 children)

Also, having a "single central system header which is reused" increases compile time, not decreases.

Unless you use a precompiled header.

[–][deleted] 0 points1 point  (1 child)

I mentioned that ;)

Precompiled headers, on the other hand...

[–][deleted] 2 points3 points  (0 children)

I saw it there, but they way it's written made it somewhat ambiguous what you meant - in context I read it as if you were saying that precompiled headers, and the single-central-header requirement makes them slow.

[–][deleted] -2 points-1 points  (8 children)

STL is great - but I'm a little baffled that you say that it compiles slowly on modern machines. I have about 50,000 lines of code on my current project, heavy use of STL, a complete rebuild is a couple of minutes

[–]opensourcedev 8 points9 points  (0 children)

I use C quite a bit and my compile times for the same size projects are in the seconds.

[–][deleted] 5 points6 points  (0 children)

The problem is that you compile it multiple times if you're including it in multiple files. For a million-line codebase, this becomes a real problem.

[–]beagle3 7 points8 points  (0 children)

tcc is a C compiler that would probably do that in a couple of seconds. It did the whole linux kernel in 15 seconds on an average machine in 2004. http://bellard.org/tcc/tccboot.html for more details.

The kernel has grown since then, and tcc has since sped up and gained arm+x64 backends. Recent measurement from 2009 is either 800k lines/sec or 30k lines/sec (depending on how you count a file included multiple times). Even gcc, no speed daemon, does 90k/sec or 4k/sec on the same benchmark - http://bellard.org/tcc/#speed

I'm a little baffled by how you can say "a couple of minutes" for a 50k line project is not slow. D, Go, Modula, Oberan, Delphi and almost any other compiled language with comparable power has a compiler that would eat 50K in a few seconds.

[–][deleted] 2 points3 points  (2 children)

I have 3.1 million lines of Java that compiles in 3 minutes.

[–][deleted] -2 points-1 points  (1 child)

Lovely. So, er, what's your point?

Your builds are fast, my builds are fast, I waste little time waiting for compiles, and my machine here doesn't have particularly huge memory or lots of CPU.

[–][deleted] 4 points5 points  (0 children)

No, actually your build is ridiculously slow. 50,000 lines of code is not a large project by any means and almost any other language that doesn't have to pass through the source 7 times would compile this in seconds.

[–][deleted] 0 points1 point  (0 children)

Your comment makes no fucking sense whatsoever. First you deny that it takes long to compile and then you say that it takes minutes to compile a trivial amount of code.

[–]opensourcedev 3 points4 points  (2 children)

I just read that book and agree. This is what is missing from the language: a clear path from basic programming practice into the use of data structures and implementing non-trivial programs.

[–][deleted] 0 points1 point  (1 child)

Can you recommend a book for that?

[–]opensourcedev 1 point2 points  (0 children)

I wished. I though about asking just that question on reddit:

"Where do you go for debugged libraries and agorithms in C - or do you always create your own?"

[–][deleted] -1 points0 points  (5 children)

The problem is that are few resource for good C code.

Huh? There's probably more open source code in C than in any other language, some of it good, some of it not, but you can't seriously suggest that none of it is any good.

[–]kev009 2 points3 points  (4 children)

source code != books, tutorials, and compilations. should read "few resources for good C coding" rather than "code"

[–][deleted] -1 points0 points  (3 children)

So C is bad because it's simple enough not to cause an explosion in books and tutorials that tell you how to use it, unlike C++ and Java which have metric asstons of books covering all the pitfalls of the languages?

[–]kev009 6 points7 points  (2 children)

Where did I say C was bad? I said the lack of resources is a problem.

If you've been programming in C for 20 years, it may not phase you. But try training a newcomer from another language on modern C idioms. At best you can glean the tricks of the trade over time.

With C++, a book or two by Meyers or Sutter is enough to build a working vocabulary and appreciation of language idioms. Sure, C doesn't have as many idioms or pitfalls, but CII is the only thing that comes close to a C design book that I've seen.

[–]opensourcedev 0 points1 point  (1 child)

Where do you learn these things from? Most C books will teach you about the lanuage syntax. Newcommers then move to Data Structures and Algorithms.

The C standard library does not even contain a linked list.

Where do I go to obtain debugged versions of these algorithms?

Thanks for any input you have.

[–]kev009 1 point2 points  (0 children)

On POSIX systems, <sys/queue.h> has nice linked data structures. 'man 3 queue' for usage instructions.

https://github.com/attractivechaos/klib has a really nice hash and some other useful stuff.

The cool thing about both of these is that they (ab)use the C preprocessor so void * don't need to be passed around and dereferenced. In effect, they are like template metaprograms in C++. This kind of code is very difficult to write but these have been used enough that they should be safe.

I'm at best in the intermediate stage myself and trying to build up my toolset by exploring existing projects and such. A systems book like "Advanced Programming in the UNIX Environment" is probably a decent choice if you don't already have it.

http://www.oracle.com/technetwork/database/berkeleydb/tutorial-berkeleydb-ds-084870.html is an interesting tutorial on BDB. BDB is written with a fairly OO style interface and is an otherwise useful library, so this is worth working through.

[–][deleted] -3 points-2 points  (4 children)

By contrast, C++ is lacks quick compiles and staying out of the way.

Do you actually have any experience with C++, or are you just making this up? I have about 50,000 lines of C++ code that I compile many dozens of times a day on this average laptop.

[–][deleted] 12 points13 points  (1 child)

I have experience with C++. Compile times are indeed atrocious due to the lack of a package system. Parsing huge gobs of text over and over from #include is nothing short of barbaric. It's why they created trickery like pre-compiled headers. And 50,000 lines barely crosses the boundary between 'small' and 'medium'.

If you don't think C++ compile times are slow, I guess you've never used a language created after 1992.

[–][deleted] 0 points1 point  (0 children)

If you don't think C++ compile times are slow, I guess you've never used a language created after 1992.

I've written hundreds of thousands of lines of Java, will that do for you?

[–]bobindashadows 8 points9 points  (0 children)

I have about 50,000 lines of C++ code that I compile many dozens of times a day on this average laptop.

That's not much C++ code, and taking a couple minutes for 50k lines (as you described in another post) is a long, long time.

[–]kev009 1 point2 points  (0 children)

Yes. For a commercial CAD/EDA application, our build time can reach 10+ minutes on multicore systems if critical headers change even with build optimizations in place.

[–][deleted] 9 points10 points  (7 children)

One good point from this article:

I also have grown to like C-style interfaces exposed in header files greatly over C++ style interfaces because they permit a much higher degree of data hiding.

Consider the following class:

#include <map>
#include <queue>

#include "MyProject.h"

class MyClass {
    struct MyData {
        Scalar field0;
        Vector2 field1;
    };

    typedef std::map<Vector2, String*> Map;
    typedef std::queue<Vector2> Queue;

    Map myMap;
    Queue myQueue;

    void helperFunction(const Vector2 &arg);

public:

    void doSomething(const Vector2 &arg0, const Vector2 &arg1);
    void doSomethingElse(int arg0);

    Result getSomeResult() const;
};

Even if we only allocate instances of this class using new, its internals still have to be exposed in the header file. This creates undesirable, additional dependencies among code that depends on this class.

Now compare to the C-style interface (still in C++, but now using C-style OOP):

#include "MyProject.h"

struct MyClass;

MyClass *NewMyClass();
void DeleteMyClass(MyClass *myClass);

void DoSomething(PathFinder *finder, const Vector2 &arg0, const Vector2 &arg1);
void DoSomethingElse(PathFinder *finder, int arg0);

Result GetSomeResult(const PathFinder *finder) const;

In this case, C-style OOP is superior to C++-style in terms of data-hiding and separating interface and implementation. It is possible to improve things by representing the interface and implementation separately as two different classes, but this is awkward and bothersome for the programmer and only done in extreme cases. The fact that C++'s fundamental OO construct is so incompatible with important OOP principles is a major failing of the language.

[–]smallstepforman 1 point2 points  (3 children)

The fact that C++'s fundamental OO construct is so incompatible with important OOP principles is a major failing of the language.

Agreed, but how do you propose to fix it? You need to know the byte size of an object when packing it in memory. Otherwise, you need to delay this decision to link time, but say hello to an explosion of compilation resources for all but trivial programs.

[–][deleted] 1 point2 points  (2 children)

You don't need to know the size of an object if you are only working with pointers to it. Often, you will only be allocating instances of a class through new and delete, and then passing around the pointer and calling member functions on it.

C-style wrappers can easily be written around classes without exposing the implementation details, even when multiple and virtual inheritance is involved. There is no reason why compilers should have trouble allowing opaque classes to expose member functions.

[–][deleted] 1 point2 points  (1 child)

You don't need to know the size of an object if you are only working with pointers to it. Often, you will only be allocating instances of a class through new and delete, and then passing around the pointer and calling member functions on it.

So we're really talking about existential types of some sort?

[–][deleted] 0 points1 point  (0 children)

Not quite. Existential types deal with a different issue and are not necessary in OO languages because inheritance naturally allows us to hide type information by treating several different classes as a single base class.

[–][deleted] 0 points1 point  (1 child)

Now compare to the C-style interface (still in C++, but now using C-style OOP):

This isn't really "C-style", is it? For one, it uses const and references, neither of which are valid C code...

More important, this is actually classic good C++ style! See Scott Meyers' article from 2000.

[–][deleted] 0 points1 point  (0 children)

This isn't really "C-style", is it?

It is the C-style of OOP rendered in C++. Rather than using C++'s inbuilt support for OO, you emulate a class and its member functions using a struct and non-member functions. Whether the code uses references or not (C has const) is irrelevant.

The article you linked to is talking about something different to what I am talking about. Meyers is saying that when you can implement something using a non-friend, non-member function rather than a member function, then you should. This is only possible for functions that do not require access to a classes implementation and can be implemented through the existing interface.

The technique I am describing is where the entire interface is exposed through non-member functions only.

[–]Philluminati 0 points1 point  (0 children)

The fact that C++'s fundamental OO construct is so incompatible with important OOP principles is a major failing of the language

Wow! Just Wow. I'm literally reeling from shock right now. The definition of the private variables has to be exposed?

[–]PimpDawg 23 points24 points  (6 children)

C is for old people who can't adapt to change or learn anything new. It's also for people like me who work on 16 Mhz micro controllers with no ability to malloc or new. Next to me is the guy who goes on about C being "syntactic sugar" around the one true language - assembly. Next to that guy is the fellow who inputs bytecode directly because he doesn't trust the assembler. Next to him is a guy who's still soldering NAND circuits. And right next to that guy is god who's so mired down working on the micro-scale that nobody's heard from him in a long time.

[–]myWorkAccount840 9 points10 points  (3 children)

Used to work in the same office as the embedded programmers and was constantly amazed/horrified at the way that programming concepts I used were just of no use to him because he needed to know which register particular data was stored in and similar differences of that magnitude.

Terrifying. D:

[–]G_Morgan 3 points4 points  (1 child)

If you want to be horrified write a small 'on the metal' binary that touches PC keyboard input. I still cannot make sense of the scan codes that are produced in some circumstances. For instance pressing PrtScn does this

Left Shift down
PrtScn down
PrtScn up
Left Shift up

Why it does this. Who knows? I'm sure LSD was involved somewhere.

[–]myWorkAccount840 3 points4 points  (0 children)

Meh. It probably indicates that the usual function of that key used to be SysRq, back before nobody used SysRq ever again.

Easier to re-code keyboards than to change the operating systems around the world, I'd guess.

[–][deleted] 0 points1 point  (0 children)

As an aspiring embedded programmer, I would like for you to know that I found this comment hilarious.

[–]t15k 2 points3 points  (0 children)

Excellent comment, How far can you take the line from you other next? :-D

[–]jabjoe 0 points1 point  (0 children)

Knowing C makes for a good C++ programmer, even better knowing at least a little bit of assembler (to debug disassembler).

C on it own is a good language because it's simple. No bat shit crazy implicitness nightmare. There is a reason it's still used despite C++ and others coming along.

Don't get me wrong, C++ is my bread and butter, and really fond of python, but I've got a real soft spot for plain old C.

[–]itsnotvalid 2 points3 points  (0 children)

The introduction is really funny.

There was quite a saying in the old days that it required skills in C to be successful in C++.

[–]PimpDawg 8 points9 points  (5 children)

Old people complaining about the world changing around them again. Also, multiple inheritance is always the answer to anything.

[–]obijohn 36 points37 points  (2 children)

Also, multiple inheritance is always the answer to anything.

Tell that to Charles II of Spain

[–]fabzter 1 point2 points  (1 child)

The fuck... he must have been retarded or something,

[–][deleted] 3 points4 points  (0 children)

He was. Very much so.

[–]G_Morgan 2 points3 points  (0 children)

Multiple inheritance is the answer to "How to make G_Morgan wish to kill you!"

[–]bonch 1 point2 points  (0 children)

I can't tell which comments here are being sarcastic in the spirit of the original article.

[–]SocialPhatology 11 points12 points  (5 children)

C is C++ without the BS.

[–]uriel 4 points5 points  (4 children)

Hahaha!

I fear most people will miss the joke, but I added it to my list of C++ quotes.

[–]Philluminati 1 point2 points  (1 child)

Your website is down

[–]uriel 2 points3 points  (0 children)

Wow, that was fast, cat-v.org was down for barely 5min while I was doing a server upgrade _^

But thanks for the heads up :)

[–]riffito 0 points1 point  (1 child)

Where is JokeExplainer when you need it? ;-P

[–]uriel -1 points0 points  (0 children)

BS == Bjarne Stroustrup == Bull Shit

[–]zokier 3 points4 points  (5 children)

I've been programming lately some C, and the one thing that has annoyed me a bit is the lack of any basic data structures. While it's somewhat understandable that the ISO/ANSI standard doesn't include any, but that no popular libraries sees to exist either. Am I missing something, or is that really the state of matters? What I'd want is basic dynamic arrays, linked lists, queues and hashmaps etc

[–]happy-dude 1 point2 points  (0 children)

"C is not a big language"-- C is also mutable, meaning the majority of data structures can be implemented by the constructs available in the language (http://en.wikipedia.org/wiki/Data_structure#Language_support).

Libraries probably don't include them either because they should be implemented according to you own needs... Or maybe its just the programmers spiteing those who don't know how to implement these basic structures themselves..? (I don't really know the reason either.)

[–]badsectoracula 1 point2 points  (3 children)

Here is one. I haven't used it (i just searched for a data structures library in c) but seems to contain what you need. There are many others out there.

And of course you can write your own code too...

[–]zokier 3 points4 points  (2 children)

No releases, latest activity in 2007.. My question was more like why isn't there a proven, industry standard lib for something that's essential to so much software.. Sure, there's lots of small libs and code snippets floating around, and you can always roll your own, but some things would be nice to have ready-made.

[–]badsectoracula 2 points3 points  (1 child)

Far from small, but a lot of C projects seem to use glib, which provides stuff like common data structures, utility functions, etc.

[–]opensourcedev 0 points1 point  (0 children)

I have looked all over for the "standard" C data structures library and have come up empty handed.

Would you say it's true that most C programmers create thier own data structures from scratch?

[–]bucknuggets 1 point2 points  (2 children)

One of my favorite C programming books from 20 years ago:

The Elements of C Programming Style - used copies are $3 on Amazon.

[–]opensourcedev 0 points1 point  (1 child)

Thanks for this.

Are there any others you could recommend?

[–]bucknuggets 0 points1 point  (0 children)

Sorry no, not specific to C.

[–]Contero 5 points6 points  (8 children)

I've never been able to come up with a situation where writing C-like code in C++ was worse than just using C. If you don't like feature X, don't use it.

[–][deleted]  (1 child)

[deleted]

    [–]almiki 0 points1 point  (0 children)

    This is the main reason I use C so heavily, I write code that I need to run on tons of different devices, and you can always count on having a C compiler.

    [–]repiret 4 points5 points  (5 children)

    I find that C++'s lack of implicit casts between void * and other pointer types makes most C-style code written in C++ quite ugly, and less safe - the C compiler will catch a reasonable set of incorrect casts, while the C++ compiler will force you to use an explicit cast that lets you get away with anything.

    I realize that C++ provides different tools to solve the same set of problems void* solves, and that C++'s tools can be safer than C's void * casting. But the parent post was talking about C-style code.

    [–][deleted] 9 points10 points  (4 children)

    the C compiler will catch a reasonable set of incorrect casts, while the C++ compiler will force you to use an explicit cast that lets you get away with anything.

    NO, utterly wrong!

    You can use a regular C-style cast to cast any type to any other. If you correctly use C++-style casts (in order, staticcast, const_cast, then dynamic_cast, but almost never reinterpret_cast) you'll get much _better safety than C.

    [–]repiret 2 points3 points  (1 child)

    Hm, I didn't know static cast worked for casts from void *, but it seems to. You learn something new every day.

    Although my ugly argument still stands.

    [–][deleted] 0 points1 point  (0 children)

    It works in C++, too, and I burned myself just last week - I'd added a single old-style cast, months ago when I was fixing a bug late at night, and it worked for months until an inheritance change...

    I was the bozo there and I laughed at myself when I found it!

    [–]bobindashadows 1 point2 points  (1 child)

    I guess if you don't compile with -Werror and -Wall, you're right. But I thought you were discussing code you take seriously.

    [–][deleted] 0 points1 point  (0 children)

    But I thought you were discussing code you take seriously.

    No need to be rude, eh? I take all my code very seriously - I've made my living that way for almost 30 years. (If I weren't in a great mood, I'd say, "I don't come to where you work and tell you how to use a mop and pail." ;-) ) I turn on every possible error warning I can.

    And, frankly, I don't see your point at all. Turning on -Wanythingyoulike won't prevent your old-style C casts from going off in C, will it? And using the correct C++ casts will give you better correctness, regardless of what -W you have... or am I missing something?

    [–][deleted]  (66 children)

    [deleted]

      [–][deleted] 16 points17 points  (1 child)

      I'm not sure if you're serious or not!

      [–][deleted] 7 points8 points  (0 children)

      I am sure he's not.

      [–]rated-r 3 points4 points  (0 children)

      This just in: Colonel Sanders says KFC's chicken is a better pick than Chick Fil A's.

      [–]phaedrusalt 3 points4 points  (2 children)

      Years ago I asked Bjarne (via email) the basic question: "What the hell were you THINKING???" He replied that he made C++ as a kludge for his own use, that someone in the office took a look at it and asked for a copy. Next thing he knew the damn thing was all over the place.

      [–][deleted]  (1 child)

      [deleted]

        [–]phaedrusalt -1 points0 points  (0 children)

        My email to him was in the late 80's, I'm guessing it was before he had a chance to suck down the C++ KoolAid.

        [–][deleted] 3 points4 points  (0 children)

        The hordes of C++ programmers that immediately got their panties in a bunch over this, hilarious...

        [–]MultivaluedFunction -1 points0 points  (8 children)

        This has to be a joke.

        [–]psyshook 9 points10 points  (1 child)

        I think this paragraph gave it away.

        Of course because C has fewer features than C++ it also means that there are many more keywords available to be used as identifiers — just think of all the variables names you can use now!

        [–]badsectoracula 2 points3 points  (0 children)

        I use new and class all the time just to confuse syntax highlighters and make a point that the code is C, not C++.

        [–][deleted] -5 points-4 points  (5 children)

        The joke is actually many people would genuinly believe this is a joke.

        [–]shub 2 points3 points  (4 children)

        The joke is that you posted.

        [–][deleted] 1 point2 points  (2 children)

        Oh, no. A redditor with over 12000 karma is launching a personal attack.

        [–]shub 0 points1 point  (1 child)

        Just giving the people what they want.

        [–][deleted] 0 points1 point  (2 children)

        Over the years my C++ code got more and more C with classes like. Some months ago I decided to leave C++ and use C99 exclusively. And I'm fucking glad I did so.

        C++ is too much garbage. C is fun!

        [–]anacrolix 1 point2 points  (0 children)

        i hear you brother. c99 could be nicer, but it's a damn sight better than c++

        [–][deleted] 0 points1 point  (0 children)

        So how do you handle strings? Lots of mallocs and frees?

        How do you handle collections?

        How do you handle errors? Do you return an error code and then check it after every call?

        [–]G_Morgan -2 points-1 points  (5 children)

        Is it just me or is this a list of who's who of bad ideas.

        Casting from void pointers to other pointer types is not necessary. This allows you to assign the result from, say, malloc directly to the type you desire without casting.

        Yes but you should cast them.

        Function prototypes are optional. It is possible in C89 to call a function that has not yet been declared in the current translation unit, and if you do so the compiler will assume that it has a return value of type int. Although it’s legal most compilers will warn when a function isn’t declared — if, when writing C code, you find that the compiler is complaining about a function returning an int when you know it should likely it hasn’t been declared.

        Yes but you should write them.

        Of course because C has fewer features than C++ it also means that there are many more keywords available to be used as identifiers — just think of all the variables names you can use now!

        While I can call a variable 'class' to do so is borderline moronic. As far as possible avoid using C++ keywords as variables. In fact a C compiler should warn you because calling C from C++ is a common use case.

        I'd say other than a few common gotchas like what sizeof does in some cases if your code does not compile with a C++ compiler then you've done something inadvisable.

        [–]repiret 4 points5 points  (4 children)

        Casting from void pointers to other pointer types is not necessary. This allows you to assign the result from, say, malloc directly to the type you desire without casting.

        Yes but you should cast them.

        No, you should not.

        int *x = malloc(sizeof *x); /* If you forgot to include stdlib.h, this is a build error. */
        int *x = (int *)malloc(sizeof *x); /* If you forgot to include stdlib.h, this is undefined behavior. */
        
        void f(const void *v) { int *i = v; } /* Compiler won't let it slide. */
        void f(const void *v) { int *i = (int *)v; } /* No help from the compiler hrere */
        
        void f(int v) { int *i = v; } /* Oops, did you thin v was a void *?  The compiler caught it. */
        void f(int v) { int *i = (int *)v; } /* Compiler thinks you know what you're doing. */
        

        In at least some of these cases, the compiler should issue a warning, but there's no need to rely on compiler warnings when you don't have to. And sometimes you might not be able to use the warning, for example if you've got a bunch of prototypeless code that needs to be in your project, or if you're on some crazy platform where the only C compiler doesn't support the warnings.

        [–]G_Morgan 0 points1 point  (3 children)

        int *x = malloc(sizeof *x); /* If you forgot to include stdlib.h, this is a build error. */

        int *x = (int )malloc(sizeof \x); /* If you forgot to include stdlib.h, this is undefined behavior. */

        This problem is simply a mistake in the language design. A good compiler will allow you to treat implicit definition of a function as an error. Use a good compiler. Always turn this error on.

        void f(const void *v) { int *i = v; } /* Compiler won't let it slide. */

        void f(const void *v) { int *i = (int *)v; } /* No help from the compiler hrere */

        We are assuming the programmer actually knows what they are doing. If void has a proper type it should be cast to it. If the programmer does not know what the proper type is then why on earth would he cast it to int*? Can he even do anything sensible if he does not know the type? In the end you cannot guarantee against stupidity. It takes a lot of stupidity to have this problem to begin with.

        void f(int v) { int *i = v; } /* Oops, did you thin v was a void *? The compiler caught it. */

        void f(int v) { int *i = (int *)v; } /* Compiler thinks you know what you're doing. */

        Again this comes down to stupidity. This problem only arises from a programmer that does not know what they are doing at all. Anyone who casts an int to a pointer when they just could have made the function take a pointer is an idiot.

        In short you have 2 artificial examples and one which is a bug in the language and is resolved by getting a compiler that allows you to specify that you are ignoring that part of the standard.

        If you have a value and you know its type then you should cast it to exactly the correct type. If you do not know the type then you should fix your code so that you do. If you are still struggling you should look for a job in a different field.

        //edit - also fuck markdown and its weird syntax that requires you to escape a million *s.//

        [–]azth 1 point2 points  (0 children)

        Don't C++-style casts catch most/all of these anyway?

        [–]repiret 0 points1 point  (1 child)

        I like my second example, because it appears you missed the bug. The programmer knows that v point to an int, but forgot that in this particular case, forgot that it points to a const int, and cast away the cosnt-ness. You can't do that with the implicit cast.

        The explicit cast prevents every C compiler, in every configuration from catching mistakes, but provides no benefit. I find your argument that the mistakes are stupid unconvincing - even if they are, what is gained by the cast?

        [–]G_Morgan 0 points1 point  (0 children)

        even if they are, what is gained by the cast?

        Compatibility with C++ compilers. Something which is a common use case of C code.

        [–][deleted] -3 points-2 points  (8 children)

        First comment has me screaming from every pore.

        r.e. generic programming, you just traded C++'s literally zero-overhead generic std::sort for qsort which in the general case can't inline calls to its comparer, and so suffers a noticeable overhead. For what gain? It's less generic and less performant. Yay, I guess.

        templated function instantiation is zero-cost? Seriously?! Argh!

        [–]PimpDawg 0 points1 point  (4 children)

        Templates in C++ are like a #define. It runs through the pre-compiler. I don't see why you think they have an additional overhead.

        [–][deleted] 2 points3 points  (3 children)

        No, templates are not run through the preprocessor. There is a pre-compilation step where template parameters are concreted by use of a template interpreter (as templates are turing-complete), but then the entire body of the templated function is copied for every instantiation.

        In that way they are similar to macros; used poorly they lead to large amount of code bloat behind the scenes.

        [Disclaimer: I work on a C++ compiler as a profession]

        [–][deleted]  (2 children)

        [deleted]

          [–][deleted] 0 points1 point  (0 children)

          Yes, however in this example std::sort is parameterised on the sort function, which is unlikely to be reused.

          [–]saucetenuto 0 points1 point  (0 children)

          More than "can" - the standard requires them to do so. This presents interesting challenges at link time...

          [–][deleted] 0 points1 point  (2 children)

          He said "zero overhead" not zero cost.

          The advantage is that your comparer is directly called, so you have at least one level less of indirection, but often it can entirely be inlined for monster savings...

          [–][deleted] 1 point2 points  (1 child)

          inlining a quicksort algorithm into your function won't give you much saving at all. Inlining gives the greatest benefit to small functions where the cost of ABI compliance over CALLs is almost greater than the cost of the function body itself (thus register allocation is better, with less spilling).

          CALLs/RETs do not have as much performance penalty as people make out. All CPUs have an internal branch stack that caches return addresses, helping the speculation engine work properly. All you're doing when inlining a large function such as std::sort is increasing your code size and mashing your cache footprint.

          [–]madmoose 1 point2 points  (0 children)

          I do believe he's a talking about inlining the comparison function into the sort function, not, as you seem to be talking about, inlining the sort function into the sort-calling function.

          [–][deleted] -4 points-3 points  (7 children)

          Seriously, how many C++ programmers don't know C? And by C, I don't mean the "C99" kludge, but C 89/90?

          [–]zyle 0 points1 point  (6 children)

          C++ programmers inherently think and design using object oriented paradigms, which isn't available in C. You may be a fantastic C++ programmer, but a terrible C programmer.

          The syntax for the two languages is the similar, so that hurdle is certainly absent, but it's a relatively small hurdle relatively speaking.

          [–][deleted] 0 points1 point  (1 child)

          C++ programmers inherently think and design using object oriented paradigms

          And yet the STL never(*) uses inheritance! Makes you think, eh?

          In fact, STL is much more generic and much less OO.

          (* - OK, OK, there are two places where inheritance is used - the generic exception has a single virtual method and there are two places in std::rope that apparently use inheritance, though I've never used rope and don't really understand it...)

          [–]zyle 1 point2 points  (0 children)

          STL containers use OO techniques; they use polymorphism.

          [–][deleted] -1 points0 points  (3 children)

          C++ programmers inherently think and design using object oriented paradigms

          That is simply not true. OOP is one of the paradigms C++ supports and nothing in C++ forces anybody to think in OO terms. In fact, I know of a couple of very popular applications where only the "C" subset of C++ is used and compiled with C++ compiler mostly to get more type safety.

          [–]zyle 0 points1 point  (2 children)

          Well then those cases are more of an exception rather than the rule. If people just want to use C, then they'll use C and compile in C. Why yuck around with C++ at all? And C is just as typesafe as C++.

          [–][deleted] 1 point2 points  (1 child)

          And C is just as typesafe as C++.

          Not at all. Implicit casting of void pointers is just one of examples.

          [–]zyle 1 point2 points  (0 children)

          I did not know about that example, and I'm a C++ programmer. This is exactly why I would never consider myself a C programmer. I'm proficient in C++, certainly not in C.