Live data from Hacker News

Tell HN: C Experts Panel – Ask us anything about C

news.ycombinator.com

261–270 of 978 posts

Re: Tell HN: C Experts Panel – Ask us anything about C

#262

Earlier quoted context omitted.

You only need two! like this

I tried, but two spaces yielded what you saw.

Huh, it also needed an extra line break before the first line of code. I didn't realize that! I've fixed it now.

Re: Tell HN: C Experts Panel – Ask us anything about C

#263

char effectively behaves as a signed type, making it unsuitable for binary operations (e.g. UTF-8 manipulation). I/O functions deal with char pointers, so using unsigned type like uint8_t requires casting back and forth. Is there any way out of this problem, and am I already breaking the aliasing rules with that cast?

Casting between the three character types is safe and doesn't violate aliasing rules. In addition, objects of all types can be accessed by lvalues of any of the three character types (though unsigned char is recommended), so there's no problem there either.

I/O functions that take a plain char* are designed to interoperate with char arrays and strings, so passing in unsigned or signed char is a sign that they aren't being used as intended. (Functions that traffic in binary data like fread/fwrite should take void*).

Re: Tell HN: C Experts Panel – Ask us anything about C

#264
post #151
post #118

Earlier quoted context omitted.

There are "projects" underway to clean up the spec where it's viewed as either buggy, inconsistent, or underspecified. The atomics and threads sections are a coupled of example. There are efforts to define the behavior in cases where implementations have converged or died out (e.g., twos complement, shifting into the sign bit). There have been no proposals to add new array types and it doesn't seem likely at the core…

> no such feature has emerged in practice Arrays with length constantly emerge among C users and libraries. They are just all incompatible because without standardization there is no convergence.

Sounds like a good use of standardization. If there is existing implementation practice, please go ahead and submit a proposal. I would be happy to champion such a proposal if you can't attend in person.

Re: Tell HN: C Experts Panel – Ask us anything about C

#265

Now that C2x plans to make two's complement the only sign representation, is there any reason why signed overflow has to continue being undefined behavior? On a slightly more personal note: What are some undefined behaviors that you would like to turn into defined behavior, but can't change for whatever reasons that be?

Just going to inject that this impacts a bunch of random optimizations and benchmarks. Just to fabricate an example: for (int i = 0; i Reasonably common idea but the compiler is allowed to assume the loop terminates precisely because signed overflow is undefined. I’m not trying to argue that signed overflow is the right tool for the job here for expressing ideas like “this loop will terminate”, but making signed over…

The compiler assumes that the loop will alwasy terminate and that assumption is wrong, because in reality there is the possibility that the loop will not terminate, since the hardware WILL overflow.

So it's not the best solution. If we want to make this behaviour for optimizations (that are to me not worthed, giving the risk of potentially critical bugs) we must make that behavior explicit, not implicit: thus is the programmer that has to say to the compiler, I guarantee you that this operation will never overflow, if it does it's my fault.

We can agree that having a number that wraps around is not a particularly good choice. But unless we convince Intel in some way that this is bad and make the CPU trap on an overflow, so we can catch that bug, this is the behaviour that we have because is the behaviour of the hardware.

Re: Tell HN: C Experts Panel – Ask us anything about C

#266

Earlier quoted context omitted.

I am sorry I do not have an answer to your question. It's a very valid one and I would be interested in any pointer to an answer. What I can say while we are on the subject, is that I have seen C code (most often C code that started its life in the 1990s, to be fair) that instead of showing an abstract struct in the public interface, showed a different struct definition. Please don't do this. Yes, when compiling nowa…

Wait, doesn't this mean that the BSD sockets API is inherently dependent on UB, casing different socket types to each other and sometimes only using the first few members, or am I misunderstanding you?

Yes and no.

The thing I am describing is when you link a compilation unit using:

  struct internal_state { int dummy; } state;
with another compilation unit that defined the same state differently:

  struct internal_state {
     int actual_meaningful_member_1;
     unsigned long actual_meaningful_member_2; } state;
As far as I know, BSD socked do not do this. Zlib was doing this (https://github.com/pascal-cuoq/zlib-fork/blob/a52f0241f72433... ), but I have had the privilege of discussing this with Mark Adler, and I think the no-longer-necessary hack was removed from Zlib.

BSD sockets probably have a different kind of UB, related to so-call “strict aliasing” rules, unless they have been carefully audited and revised since the carefree times in which they were written. I am going to have to let you read this article for details (example st1, page 5): https://trust-in-soft.com/wp-content/uploads/2017/01/vmcai.p...

Re: Tell HN: C Experts Panel – Ask us anything about C

#267

Any plans to add semantics for exceptional situations such as divide by zero and dereferencing a null pointer? https://blog.regehr.org/archives/232 Or incorporating features from this 14 item list? https://blog.regehr.org/archives/1180 As it appears these have failed: https://blog.regehr.org/archives/1287

The problem is that if the checks are always performed, the object code is significantly slowed down. If all computers supported the checking in hardware, then we could do it. You don't really want the current C approach (signal) to trigger except in an emergency, because there is no way to insert cleanup/retry/etc. recovery code via a signal handler.

Re: Tell HN: C Experts Panel – Ask us anything about C

#268
post #162

Earlier quoted context omitted.

So in a corner case where you have a loop that iterates over all integer values (when does this ever happen?) you can optimize your loop. As a consequence, signed integer arithmetic is very difficult to write while avoiding UB, even for skilled practitioners. Do you think that's a useful trade-off, and do you think anything can be done for those of us who think it's not?

No, it's exactly the opposite. Without UB the compiler must assume that the corner case may arise at any time. Knowing it is UB we can assert `n+1 > n`, which without UB would be true for all `n` except INT_MAX. Standardising wrap-on-overflow would mean you can now handle that corner case safely, at the cost of missed optimisations on everything else.

I/we understand the optimization, and I'm sure you understand the problem it brings to common procedures such as DSP routines that multiply signed coefficients from e.g. video or audio bitstreams:

for (int i = 0; i If inputA[i] * inputB[i] overflowed, why are my credit card details at risk? The question is: can we come up with an alternate behaviour that incorporates both advantages of the i<=N optimization, as well as leave my credit card details safe if the multiplication in the inner loop overflowed? Is there a middle road?

Re: Tell HN: C Experts Panel – Ask us anything about C

#270

Earlier quoted context omitted.

You can very easily make a struct consisting of a pointer and length, is adding such a thing to the standard really a big deal? Personally, I don't see a problem with passing two arguments.

- In your example there's no guarantee that the length will be accurate, or that the data hasn't been modified independently elsewhere in the program. - In other words you've created a fantastic shoe-gun. One update line missed (either length or data, or data re-used outside the struct) and your "simple" struct is a huge headache, including potential security vulnerabilities. - Re-implementing a common error prone th…

I mean, this is C so "fantastic shoe-gun" is part of the territory. But in C you can wrap this vector struct in an abstract data type to try to prevent callers from breaking invariants.
Post reply on HN