| Deutsch English Français Italiano |
|
<878qz85qr7.fsf@nosuchdomain.example.com> View for Bookmarking (what is this?) Look up another Usenet article |
Path: ...!fu-berlin.de!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Keith Thompson <Keith.S.Thompson+u@gmail.com>
Newsgroups: comp.lang.c
Subject: Re: "undefined behavior"?
Date: Thu, 13 Jun 2024 17:09:48 -0700
Organization: None to speak of
Lines: 70
Message-ID: <878qz85qr7.fsf@nosuchdomain.example.com>
References: <666a095a$0$952$882e4bbb@reader.netnews.com>
<8t3k6j5ikf5mvimvksv2t91gbt11ljdfgb@4ax.com>
<666a18de$0$958$882e4bbb@reader.netnews.com>
<87y1796bfn.fsf@nosuchdomain.example.com>
<666a2a30$0$952$882e4bbb@reader.netnews.com>
<87tthx65qu.fsf@nosuchdomain.example.com>
<v4dtlt$23m6i$1@dont-email.me>
<87plsk5xbz.fsf@nosuchdomain.example.com>
<v4g02k$2gfm9$2@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Date: Fri, 14 Jun 2024 02:09:49 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="10f324c947246626491173dedfdc5917";
logging-data="2650136"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1838Vp461GGqbfnOHpnTbT9"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Cancel-Lock: sha1:sfabvF0RBKD1RAL1UfZPM2oSGO4=
sha1:hKMsqzDiT1if2ldktUXQkaDdb8o=
Bytes: 4612
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
> On 13/06/2024 22:47, Keith Thompson wrote:
>> Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
>>> On 13/06/2024 01:33, Keith Thompson wrote:
>>>> printf is a variadic function, so the types of the arguments after
>>>> the format string are not specified in its declaration. The printf
>>>> function has to *assume* that arguments have the types specified
>>>> by the format string. This:
>>>> printf("%d\n", foo);
>>>> (probably) has undefined behavior if foo is of type size_t.
>>>>
>>> And isn't that a nightmare?
>> Not at all. Compilers commonly diagnose mismatches when the format
>> string is a string literal, as it most commonly is. The format
>> specifier for size_t is "%zu", since C99.
>>
>>>> There is no implicit conversion to the expected type. Note that
>>>> the format string doesn't have to be a string literal, so it's
>>>> not always even possible for the compiler to check the types.
>>>> Variadic functions give you a lot of flexibility at the cost of
>>>> making some type errors difficult to detect.
>>>> (I wrote "probably" because size_t *might* be a typedef for unsigned
>>>> int, and there are special rules about arguments of corresponding
>>>> signed and unsigned types.)
>>>
>>> We just can't have size_t variables swilling around in prgrams for
>>> these reasons.
>> We can and do.
>>
> And this is how things break.
>
> Now, running a third party editor under your control so that user can
> edit an text and return control and the edited text back to you when
> he exits the editor. Yes, I understand that this is a difficult thing
> to do, the software engineeering isn't consistent, and theway you have
> to do it may change from one version of C to another.
> But printing out a variable which holds the length of a string? And
> something so basic breaks from one version of C to the next? We should
> ahave no tolerance for that at all.
What broke? And how would *you* print the result of strlen()?
strlen() has returned a result of type size_t since C89/C90.
C99 (that's 25 years ago) added the "%zu" format specifier. Today,
you're unlikely to find an implementation that doesn't support
printf("%zu\n", strlen(s));
But even if you need to deal with pre-C99 implementations for some
reason, this:
printf("%lu\n", (unsigned long)(strlen(s));
works reliably in C90, and works in C99 and later as long as size_t is
no wider than unsigned long -- and even then it breaks (printing an
incorrect value) only if the actual value returned by strlen(s) exceeds
ULONG_MAX, which is at least 4294967295. If you're using 4-gigabyte
strings, you probably want to avoid calling strlen() on them anyway.
This:
printf("%d\n", strlen(s));
has *never* been valid (it has undefined behavior unless the
implementation you're using happens to make size_t a typedef for
unsigned int and the value doesn't exceed INT_MAX, which might be
as small as 32767).
We're simply not going to throw away the last quarter century of
progress in C and go back to C90. You can if you like, but don't
expect anyone else to follow you.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */