Live data from Hacker News

A critique of "How to C in 2016"

github.com

91–100 of 181 posts

Re: A critique of "How to C in 2016"

#91
post #75
post #32

One of the most important reasons to use calloc, other than the zeroing of the allocated memory, is the fact that it checks for integer overflows (at least on most implementations). For example, when allocating an array of n elements, in malloc you would do something like the following: ptr = malloc(sizeof(int) * n); Which could potentially lead to an overflow of the size passed to malloc, hence allocating a signific…

Using calloc instead of malloc, just for checking arithmetic overflow, is superfluous. You can always write a check or a wrapper for malloc that does that automatically. It is so easy I can write it here: _Bool Check( const size_t a , const size_t b ) { if( a > SIZE_MAX / b ) { return false; } return true; } (If proper warnings are enabled, it also provides extra integer type checking.)

Agreed, but there's little point in reinventing the wheel in this particular case.

Re: A critique of "How to C in 2016"

#92
post #91
post #75

Earlier quoted context omitted.

Using calloc instead of malloc, just for checking arithmetic overflow, is superfluous. You can always write a check or a wrapper for malloc that does that automatically. It is so easy I can write it here: _Bool Check( const size_t a , const size_t b ) { if( a > SIZE_MAX / b ) { return false; } return true; } (If proper warnings are enabled, it also provides extra integer type checking.)

Agreed, but there's little point in reinventing the wheel in this particular case.

There is no reinventing going on here. In C you have to write relatively low level code. This includes manually calling allocs for objects, which includes the code for checking your arithmetic. At some point you will have to write that code. If you are smart you will wrap it into a function.

Re: A critique of "How to C in 2016"

#93

Earlier quoted context omitted.

Unfortunately, there are real world systems with C compilers that do not have 8 bit bytes. It's easy to forget the embedded world. C is one of the very, very few languages that you can reasonably expect to run on your weird embedded microprocessor, microcontroller, DSP, or whatever. Bit, however, means "binary digit". That's the literal definition of the word. Historical usage of the word "byte" has varied.

> C is one of the very, very few languages that you can reasonably expect to run on your weird embedded microprocessor, microcontroller, DSP, or whatever. I'm not an expert on DSP processing in any way, but I'd argue that if the environment is so peculiar that it doesn't have 8-bit bytes, you won't be able to use so many of the (formally optional) parts of C that you might as well call your code "weirdC" and do witho…

You can use char, and for the most part you won't notice any difference, until you start looking at the memory display in your IDE and have a short-lived WTF moment. A c-string looks strange in the memory view because there's a NULL octet between each character but that's an implementation detail that you don't really notice 99% of the time, because everything on the processor is designed to use 16-bit words. If you write a buffer of chars to the UART tx register, it will only put the half of the word with the character data onto the wire, just like with any other microcontroller, just like with PySerial, and just like with JS and websockets. That's why the C standard doesn't say a char is 8-bits, it just says that sizeof(char) is 1. I would argue that any code doing anything under the assumption that a char variable occupies 8 bits in memory and that the next char in an array is physically adjacent to it with no wasted space in between is just poorly-written and inherently not portable.

As for why this is the case, Generally DSPs are designed to do a few tasks very well (multiply-accumulate being the most obvious example, simultaneous reads from X and y memory, etc.) and are generally optimized for a specific word size. If you really need to access an octet on E.g. A 16-bit TI DSP you can, you just need to shift and mask. That's obviously not very efficient, because that's not really what it's optimized for. If that's what you really need, you picked the wrong part. You're gonna be filter-/FFT-/DCT-/whatever-ing way more 12 or 16-bit ADC samples per second, per dollar, and per milliWatt on that 16-bit DSP than you would be on your octet-addressable MSP430.

Regarding "Normal" c libraries, If they're valid C they should work just fine for the most part, With some obvious exceptions: you're not going to have a fun time with your "floats" on a processor without FP HW. That's why there's a standard, if you're not relying on undefined or implementation-defined behavior, you'll be fine(ish)

Re: A critique of "How to C in 2016"

#94
post #5

> Zeroing memory often means that buggy code will have consistent behavior; by definition it will not have correct behavior. And consistently incorrect behavior can be more difficult to track down. I agree that using calloc should not be an excuse for writing sloppy initialization code. But in my experience, inconsistently incorrect behaviour (e.g. heisenbugs that tend to appear and disappear depending on the content…

Great point.

This is the part I disagree with most strongly:

> And consistently incorrect behavior can be more difficult to track down.

Re: A critique of "How to C in 2016"

#95

Ironic that he begins by taking issue with the idea that you should avoid writing C if you can, then proceeds to provide the best evidence possible for why it's true. Why on Earth would you voluntarily code in a language where people can debate something as simple as which type to use for integers, unless you absolutely had to?

You voluntarily code in C for the same reason that your OS kernel's 'yield' is written in assembly. How do you push the addressing mode register to the stack when switching to another task in your high level language of choice?

Re: A critique of "How to C in 2016"

#96
> The first rule of C is don't write C if you can avoid it.

My C skills are non-existent, but it occurs to me while reading the response that when two people who have so carefully considered the subject can arrive at such different places... then yes, you probably shouldn't write C if you can avoid it.

Re: A critique of "How to C in 2016"

#97
post #92
post #91

Earlier quoted context omitted.

Agreed, but there's little point in reinventing the wheel in this particular case.

There is no reinventing going on here. In C you have to write relatively low level code. This includes manually calling allocs for objects, which includes the code for checking your arithmetic. At some point you will have to write that code. If you are smart you will wrap it into a function.

I don't see the point of the discussion, that piece of code (or relatively equivalent), is already being performed by a libC function (calloc, in this case), how is that less convenient than you writing it yourself?

It has nothing to do with how smart you are or how low level C is, you are effectively reinventing that part of calloc by wrapping malloc.

Re: A critique of "How to C in 2016"

#98

Ironic that he begins by taking issue with the idea that you should avoid writing C if you can, then proceeds to provide the best evidence possible for why it's true. Why on Earth would you voluntarily code in a language where people can debate something as simple as which type to use for integers, unless you absolutely had to?

Because it's simple and low-overhead and compilers for it exist on every lump of hardware I've ever had to work with, from a clunky x64 to a PIC to a TigerSHARC to a bizarre DSP thingy from a tiny fab lab somewhere. A great many of the problems that people experience with C code can actually be nullified (zing!) by finding a competent C programmer who does the job properly. A tool being easy to misuse doesn't mean we…

The key phrase here is "if you can avoid it".

When your target platform is an 8-bit microcontroller or an embedded system with hard real-time requirements, your options are very limited.

But there are plenty of situations where there are alternatives, and often these allow you to solve your problem in less time, with much lower risk of bugs than in C. As always in life, one has to evaluate one's options, consider their respective advantages and weaknesses and then make a choice.

If I had to write a document like that, I would use a different phrasing from "if you can avoid it". But the sentiment - to avoid using C where superior alternatives exist[1] - is something I agree with.

> A great many of the problems that people experience with C code can actually be nullified (zing!) by finding a competent C programmer who does the job properly.

That is kind of like saying the solution to traffic accidents is only letting people drive that don't cause accidents or demand of people that they drive sufficiently carefully. Sure, that is something worth wishing for - but it is not very realistic to expect this to actually happen.

Not that I disagree that C is a very demanding language. Even the best programmers make mistakes. But this is the reason the author of the original document the linked article refers to advised people to avoid C where possible. Most programmers will be better off for most of their projects with a language like Go, or Python or whatever.

[1] Of course, if by "alternatives" I mean languages like Perl, Python or Ruby, it is worth keeping in mind that their main implementations are written in C.

Re: A critique of "How to C in 2016"

#99
post #38

Earlier quoted context omitted.

As a matter of fact, GCC extensions are de facto standards at this point. Clang had to copy most of them. Same with bytes not being 8 bits. Nobody will ever make a system where that's not the case anymore. You'd break de facto compatibility with almost all C code for no reason. Market realities trump making systems "for fun".

>You'd break de facto compatibility with almost all C code for no reason. The authors of that code should have written portable code if they didn't want it to break.

Texhnically, they did. The go to compiler for years was GCC, with all the GNU extensions turned on. The problem is that those extensions were classically on by default, so it was very easy to just use them without thinking too much about it.

Re: A critique of "How to C in 2016"

#100

Earlier quoted context omitted.

Those compilers exist because of path dependency from unix not from any unique qualities of C

This makes no sense and I believe you are incorrect. When Analog Devices churned out the TigerSHARC processor, they did not decide to write a C compiler for it because of unix path dependencies.

When Analog Devices churned out the TigerSHARC processor they wrote a c compiler because "C is what you use for low level code" not Forth, Pascal, Modula, Ada, Fortran, Algol, a lisp or any of the other hundreds of programming languages that have been used to write programs directly on metal on computers that the TigerSHARC outclasses by magnitudes.

and "c is what you use for low level code" because decades of Unix. Decades of C being the lowest (non-assembly) level of programmers' systems, decades of being the only language that doesn't make you install an additional runtime, decades of accumulated wisdom...

But those are a side effects of Unix winning, not C qua C.

Post reply on HN