Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> It's one less thing to think about.

I've been a professional C++ programmer for almost two decades (and a C++ amateur for almost a decade before that). I've written large amounts of fairly advanced C++ using the latest standards.

My current job however, is all plain C.

One of the interesting (and, for a C++ fan like me, disturbing) things I've found is that the cognitive load is much lower when writing plain well-structured C.

Sure, you need to remember to release that lock and free that memory but this you can do in a very structured way. What you win over C++ is that you don't need to view each line of code with suspicion ("What happens if this line throws an exception?", "I wonder what this line will cost in terms of performance?", "Could this operation cause a cascading destruction of objects I'm going to access further down?").

I love RAII, yet I've debugged enough crashes where "seemingly innocuous operation destructs some local object that has an owning reference to an object that shouldn't be destructed just yet and BAM!", that I'm beginning to doubt its usefulness outside of an exception-generating language (in C++ it's essential for proper exception-handling).



Even from a C amateur point of view I feel the same way in my learning of the language. I can’t speak to multithreading or very large applications yet— but the view from the ground looking up is that C is relatively straightforward. The small size of the language is something of a relief.


It's not very surprising for me, because C is a simpler language and it's easy to paint yourself into a corner with C++.

The critical question is: what does the error rate look like for code of similar complexity? It's very possible that C programmers will try to keep things simple, because the language doesn't support them and they have to be extra careful. The flip-side is that they probably can't develop projects as complex as C++ would enable them to.


> Sure, you need to remember to release that lock and free that memory

It's always bothered me how complex of an operation people seem to think this is.

    errno = pthread_mutex_lock(&m);
    if (errno == 0) {
       do_something();
       pthread_mutex_unlock(&m);
    }
Short of a segfault or 'do_something' doing something really, unusually stupid, you can't avoid freeing the mutex.


Yeah, most projects don't consist of a single function locking and unlocking a mutex. :) Try doing the same in five 200 LOC functions with multiple returns when three different threads are sharing the data, for 10 years, with a yearly personnel turnover of 20%.


Been there done that, fought similar problems. Deadlocks abound.

Only difference? We were in Python.


Something really unusually stupid like returning from the function (assuming do_something() is a standin for arbitrary code, not specifically a function call)?

This is not even remotely the worst thing about mutexes though, so it wouldn't be why I would suggest avoiding them.


Honestly, to help avoid mistakes, I would keep it as a function call. Sure, it adds to the stack depth, but it also ensures a separate return doesn't cause the lock to be lost.

There's also the goto pattern, but anytime you separate a lock from an unlock by more than a screen's worth of text, they're forgotten.


And inline functions don't even add stack depth. It's still something that happens manually though. Every item that needs to be done manually and doesn't cause obvious failures when not done adds to development costs.


And this is my unpopular complaint of programming in Rust, there is so much complexity not to do with the type system that reasoning becomes a pain.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: