On 18/03/2024 16:00, Martin Uecker via Gcc wrote:
Am Montag, dem 18.03.2024 um 14:29 +0100 schrieb David Brown:
On 18/03/2024 12:41, Martin Uecker wrote:
Hi David,
Am Montag, dem 18.03.2024 um 10:00 +0100 schrieb David Brown:
Hi,
I would very glad to see this change in the standards.
Should "byte type" include all character types (signed, unsigned and
plain), or should it be restricted to "unsigned char" since that is the
"byte" type ? (I think allowing all character types makes sense, but
only unsigned char is guaranteed to be suitable for general object
backing store.)
At the moment, the special type that can access all others are
all non-atomic character types. So for symmetry reasons, it
seems that this is also what we want for backing store.
I am not sure what you mean by "only unsigned char". Are you talking
about C++? "unsigned char" has no special role in C.
"unsigned char" does have a special role in C - in 6.2.6.1p4 it
describes any object as being able to be copied to an array of unsigned
char to get the "object representation".
The same is not true for an
array of "signed char". I think it would be possible to have an
implementation where "signed char" was 8-bit two's complement except
that 0x80 would be a trap representation rather than -128. I am not
sure of the consequences of such an implementation (assuming I am even
correct in it being allowed).
Yes, but with C23 this is not possible anymore. I think signed
char or char should work equally well now.
I have just noticed that in C23, the SCHAR_MIN is -128 (or -2 ^ (N-1) in
general), eliminating the possibility of having a trap value for signed
char (or any other integer type without padding bits). There's always a
bit of jumping around in the C standards to get the complete picture!
But as I said in another post, I still worry a little about the unsigned
to signed conversion being implementation-defined, and therefore not
guaranteed to work in a way that preserves the underlying object
representation. I think it should be possible to make a small change to
the description of unsigned to signed conversions to eliminate that.
I see people making a lot of assumptions in their embedded programming
that are not fully justified in the C standards. Sometimes the
assumptions are just bad, or it would be easy to write code without the
assumptions. But at other times it would be very awkward or inefficient
to write code that is completely "safe" (in terms of having fully
defined behaviour from the C standards or from implementation-dependent
behaviour). Making your own dynamic memory allocation functions is one
such case. So I have a tendency to jump on any suggestion of changes to
the C (or C++) standards that could let people write such essential code
in a safer or more efficient manner.
That something is undefined does not automatically mean it is
forbidden or unsafe. It simply means it is not portable.
That is the case for things that are not defined in the C standards, but
defined elsewhere. If the behaviour of a piece of code is not defined
anywhere for the toolchain you are using, then it is inherently unsafe
to use. ("Forbidden" is another matter. It might be "forbidden" by
your coding standards, or your boss, but the language and tools don't
forbid things!)
Something that is not defined in the C standards, but defined in your
compiler manual or additional standards (such as POSIX) is safe to use
but limited in portability.
And of course something that is "inherently unsafe" may be considered
safe in practice, by analysing the generated object code or doing
exhaustive testing.
I think
in the embedded space it will be difficult to make everything well
defined.
Yes, that is absolutely true. (And it is even more difficult if you try
to restrict yourself to things with full definitions in the C standards
or explicit implementation-defined behaviour documented by toolchains.
You almost invariably need some degree of compiler extensions for parts
of the code.)
But I want to reduce to the smallest practical level the amount of code
that "works in practice" rather than "known to work by design".
But I fully agree that widely used techniques should
ideally be based on defined behavior and we should change the
standard accordingly.
Yes, where possible and practical, the standard provide the guarantees
that programmers need. Failing that, compiler extensions are good too -
I'd be very happy with a GCC variable __attribute__ "backing_store" that
could be applied to allocator backing stores and provide the aliasing
guarantees needed. (It might even be needed anyway, to work well with
the "malloc" attribute, even with your change to the standard.)
David