Live data from Hacker News

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

news.ycombinator.com

891–900 of 978 posts

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

#891
post #327

Earlier quoted context omitted.

You do have to understand that compiler teams aren't saying something like "this triggers UB, quick just replace it with noop." It's just something that naturally happens when you need to reason about code. For example, consider a very simple statement. let array[10]; let i = some_function(); print(array[i]); The function might not even be known to the compiler at compilation time if it was from a DLL or something. B…

> ["]I can use that information!" Yes, that is a perfect example of buggy compiler handling of undefined behaviour. A non-buggy compiler would either behave in a manner chacteristic of the environment (ie read address array+i), ignore the situation entirely (which also results in reading array+i), or (preferably) issue a error to the effect of "possible array access out of bounds, suggest 'assert(i<10);' here".

Very well put (deliberately using the exact terminology used in the standard)!

Can we just make that binding again? After all, it used to be.

It should be obvious to compiler writers what the intention of the standard is, because it says so in the dang text, but since this was downgraded to a note and you are technically not in violation if you do something different, everyone now acts as if doing the exact opposite of what is written there is somehow OK.

The downgrade to note-status seemed to be predicted on the idea implementors can be trusted to do The Right Thing™ in these cases. It is now evidently clear that they cannot, so we have to force them.

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

#892
post #876

Earlier quoted context omitted.

should be typedef struct {uint8_t *data, *dataend} if I'm not mistaken :)

What are the advantages of saving the end as a pointer? Genuinely curious. Seems like a length allows the end pointer to be quickly calculated (data + len), while being more useful for comparisons, etc.

You can remove the first k elements of a view with data += k.

With the length you would need to do data += k; length -= k

Especially if you want to use it as safe iterator, you can do data++ in a loop

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

#893

Earlier quoted context omitted.

I don't think it's a myth so much as a misunderstanding of terminology. If an implementation defines some undefined behavior from the standard, it stops being undefined behavior at that point (for that implementation) and is no longer something you need to avoid except for portability concerns. You're exactly right that this is why there is a distinction between conforming and strictly conforming code.

The problem is that under modern interpretation, even if some parts of the Standard and a platform's documentation would define the behavior of some action, the fact that some part of the Standard would regards an overlapping category of constructs as invoking UB overrides everything else.

I could imagine misguided readings of some coding standard advice that would lead to that interpretation, but it's still not an interpretation that makes sense to me.

Implementations define undefined behavior all the time and users rely on it. For instance, POSIX defines that you can convert an object pointer into a function pointer (for dlsym to work), or implementations often rely on offsets from a null pointer for their 'offsetof' macro implementation.

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

#894

Earlier quoted context omitted.

This sounds like something memcpy would do already for you?

A 36-bit system with (it sounds like) 9-bit bytes stores bit 8 of a int in bit 8 of a char, and bit 9 of the int in bit 0 of the next char; memcpy won't change that. They're asking for somthing like: unsigned int x = in[0] + 512*in[1] + 512*512*in[2] + 512*512*512*in[3]; /* aka x = *(int*)in */ out[0] = x & 255; x>>=8; out[1] = x & 255; x>>=8; out[2] = x & 255; x>>=8; out[3] = x & 255; /* *not* aka *(int*)out = x */

The amount of effort for a compiler to process optimally all 72 variations of "read/write a signed/unsigned 2/4/8-byte big/little-endian value from an address that is aligned on a 1/2/4/8-byte boundary" would be less than the amount of effort required to generate efficient machine code for all the ways that user code might attempt to perform such an operation in portable fashion. Such operations would have platform-independent meaning, and all implementations could implement them in conforming fashion by simply including a portable library, but on many platforms performance could be enormously improved by exploiting knowledge of the target architecture. Having such functions/intrinsics in the Standard would eliminate the need for programmers to choose between portability and performance, by making it easy for a compiler to process portable code efficiently.

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

#895

Earlier quoted context omitted.

When I wrote that, I had in mind the observation about continued recalculation of buffer len. My suggestion has no such thing. It looks so good that I imagine this was probably how it was intended to be used. With that in mind, isn't it the user's job to know the size of the buffers he's using? Doesn't expecting that the function know about buffer size go against the single responsibility principle? I'm new to C, in…

The problem in practice is that you do not write “hello” and “world” to the destination buffer. You write data that is computed more or less directly from user inputs. Often a malicious user. So the user only needs to find a way to make the data longer than the developer expected. This may be very simple: the developer may have written a screensaver to accept 20 characters for a password, because who has a longer pas…

An analogous seprintf() would probably be a good thing to add too, where the buffer end is passed in instead of a buffer length. I would still have it return a pointer to the end of what was copied. Anyone can calculate the length if they need to, by subtracting the original pointer from the returned pointer.

    char *seprintf(char *str, char *end, const char *format, ...);

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

#896

What’s the current committee thinking on providing locale-independent conversions from potentially-invalid UTF-8 to valid UTF-8, from potentially-invalid UTF-8 to valid UTF-16, and from potentially-invalid UTF-16 to valid UTF-8 (i.e. replacing ill-formed sequences with yhe REPLACEMENT CHARACTER)?

If you changed UTF-16 to UTF-32 or UCS-4 I'd support it. I think there are already implementations that use the replacement character for all "impossible" codes.

What’s your use case for UTF-32?

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

#897

Earlier quoted context omitted.

A 36-bit system with (it sounds like) 9-bit bytes stores bit 8 of a int in bit 8 of a char, and bit 9 of the int in bit 0 of the next char; memcpy won't change that. They're asking for somthing like: unsigned int x = in[0] + 512*in[1] + 512*512*in[2] + 512*512*512*in[3]; /* aka x = *(int*)in */ out[0] = x & 255; x>>=8; out[1] = x & 255; x>>=8; out[2] = x & 255; x>>=8; out[3] = x & 255; /* *not* aka *(int*)out = x */

The amount of effort for a compiler to process optimally all 72 variations of "read/write a signed/unsigned 2/4/8-byte big/little-endian value from an address that is aligned on a 1/2/4/8-byte boundary" would be less than the amount of effort required to generate efficient machine code for all the ways that user code might attempt to perform such an operation in portable fashion. Such operations would have platform-i…

I'm not disagreeing, just showing code to illustrate why memcpy doesn't work for this. Although I do disagree that writing a signed value is useful - you can eliminate 18 of those variations with a single intmax_t-to-twos-complement-uintmax_t function (if you drop undefined behaviour for (unsigned foo_t)some_signed_foo this becomes a no-op). A set of sext_uintN functions would also eliminate 18 read-signed versions. Any optimizing compiler can trivially fuse sext_uint32(read_uint32le2(buf)), and minimal implementations would have less boilerplate to chew through.

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

#898

Are there any plans to add support for multiple register return values to C?

What are you asking for? Do you mean that if you return a small struct from a function, the fields are placed in registers instead of memory, if they can fit? This is up to the ABI, not the standard, to define, and some ABIs already do that.

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

#899

Are there any plans to "clean up C"? A lot of effort has been put into alternative languages, which are great, but there is still a lot of momentum with C, and it seems that a lot of improvements that could be done in a backwards compatible way and without introducing much in the way of complexity. For example: - Locking down some categories of "undefined behaviour" to be "implementation defined" instead. - Proper ar…

The difference between "Undefined behavior", as the term is used in the Standard, and "Implementation-Defined Behavior", is that implementations are required to document at least some kind of guarantee about the behavior of the latter, even in cases where guaranteeing anything about behavior would be expensive, but nothing that could be guaranteed about the behavior would be useful.

What is needed is a category of actions where implementations (which I would call "conditionally-defined", where implementations would be required to indicate via "machine-readable" means [e.g. predefined macros, compiler intrinsics, etc.] all possible consequences (one of which would be UB), from which the implementation might choose in Unspecified fashion. If an implementation reports that it may process signed arithmetic using temporary values that may, at the compiler's leisure, be of an unspecified size that's larger than specified, but signed overflow will have no effect other than to yield values that may be larger than their type would normally be capable of holding, then the implementation would be required to behave in that fashion if integer overflow occurs.

In general, the most efficient code meeting application requirements could be generated by demanding semantics which are as loose as possible without increasing the amount of user code required to meet those requirements. Because different implementations are used for different purposes, so single set of behavioral guarantees would be optimal for all purposes. If compilers are allowed to reject code that demands guarantees an implementation doesn't support, then the choice of what guarantees to support could safely be treated as a Quality of Implementation issue, but the behavior of code that claims to support guarantees would be a conformance issue.

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

#900

A few proposals: Why not mandate a warning every time the compiler detects and makes use of UB? It would solve SO many issues. If you are looking to improve security of C programs, then letting the user know what the compiler does should be number one. Try to convert as many UB's to Platform specific, as possible would also be a big help. I would love to see native vector types. Its time. Vector types are now more co…

A multiple-level break is a good idea, but I think that Java's labeled break is a better way to do it:

    find_in_array_loop:
    for(i = 0; i 
Post reply on HN