Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #161421 > unrolled thread
| Started by | SIMON <invalid@invalid.invalid> |
|---|---|
| First post | 2021-06-13 23:08 +0100 |
| Last post | 2021-07-11 02:14 -0700 |
| Articles | 20 on this page of 34 — 10 participants |
Back to article view | Back to comp.lang.c
#include <stdint.h> SIMON <invalid@invalid.invalid> - 2021-06-13 23:08 +0100
Re: #include <stdint.h> Bart <bc@freeuk.com> - 2021-06-13 23:27 +0100
Re: #include <stdint.h> Bart <bc@freeuk.com> - 2021-06-13 23:57 +0100
Re: #include <stdint.h> Philipp Klaus Krause <pkk@spth.de> - 2021-06-14 09:03 +0200
Re: #include <stdint.h> Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-06-14 01:23 -0700
Re: #include <stdint.h> Philipp Klaus Krause <pkk@spth.de> - 2021-06-14 12:31 +0200
Re: #include <stdint.h> Bart <bc@freeuk.com> - 2021-06-14 11:54 +0100
Re: #include <stdint.h> James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-06-13 18:34 -0400
Re: #include <stdint.h> Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-06-13 23:34 +0100
Re: #include <stdint.h> Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-06-13 17:48 -0700
Re: #include <stdint.h> Philipp Klaus Krause <pkk@spth.de> - 2021-06-14 09:09 +0200
Re: #include <stdint.h> Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-06-14 01:24 -0700
Re: #include <stdint.h> Philipp Klaus Krause <pkk@spth.de> - 2021-06-14 12:30 +0200
Re: #include <stdint.h> Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-06-24 10:31 -0700
Re: #include <stdint.h> Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-06-24 11:28 -0700
Re: #include <stdint.h> Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-07-11 02:49 -0700
Re: #include <stdint.h> Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-07-11 15:30 -0700
Re: #include <stdint.h> Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-07-16 03:33 -0700
Re: #include <stdint.h> Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-07-16 12:31 -0700
Re: #include <stdint.h> Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-09-30 07:07 -0700
Re: #include <stdint.h> Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-09-30 08:42 -0700
Re: #include <stdint.h> Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-10-06 03:55 -0700
Re: #include <stdint.h> Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-10-06 07:06 -0700
Re: #include <stdint.h> James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-10-06 11:47 -0400
Re: #include <stdint.h> Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-10-06 09:35 -0700
Re: #include <stdint.h> Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-10-06 10:06 -0700
Re: #include <stdint.h> James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-10-06 17:40 -0400
Re: #include <stdint.h> Branimir Maksimovic <branimir.maksimovic@icloud.com> - 2021-10-06 22:14 +0000
Re: #include <stdint.h> James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-10-06 20:06 -0400
Re: #include <stdint.h> Branimir Maksimovic <branimir.maksimovic@icloud.com> - 2021-10-07 02:15 +0000
Re: #include <stdint.h> Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-06-24 22:34 +0100
Re: #include <stdint.h> Öö Tiib <ootiib@hot.ee> - 2021-06-24 15:01 -0700
Re: #include <stdint.h> Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-06-24 15:26 -0700
Re: #include <stdint.h> Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-07-11 02:14 -0700
Page 1 of 2 [1] 2 Next page →
| From | SIMON <invalid@invalid.invalid> |
|---|---|
| Date | 2021-06-13 23:08 +0100 |
| Subject | #include <stdint.h> |
| Message-ID | <sa5vrs$7d3$1@dont-email.me> |
What changes do I need to make to get the correct values for the last
two items in this program:
> #include <stdio.h>
> #include <stdint.h>
> #include <limits.h>
>
> int main()
> {
> printf("INT_MAX : %d\n", INT_MAX);
> printf("INT_MIN : %d\n", INT_MIN);
> printf("LONG_MAX : %ld\n", (long)LONG_MAX);
> printf("LONG_MIN : %ld\n", (long)LONG_MIN);
> printf("UINT_MAX : %u\n", (unsigned int)UINT_MAX);
> printf("ULONG_MAX : %lu\n", (unsigned long)ULONG_MAX);
> printf("USHRT_MAX : %d\n", (unsigned short)USHRT_MAX);
> printf("\nFrom stdint.h: \n");
> printf("INT8_MAX : %d\n", INT8_MAX);
> printf("INT16_MAX : %d\n", INT16_MAX);
> printf("INT32_MAX : %d\n", INT32_MAX);
> printf("INT64_MAX : %lld\n", INT64_MAX);
> printf("UINT8_MAX : %d\n", UINT16_MAX);
> printf("UINT16_MAX : %d\n", UINT16_MAX);
> printf("UINT32_MAX : %d\n", UINT32_MAX);
> printf("UINT64_MAX : %lld\n", UINT64_MAX);
> }
I am using Windows 10 64 bit machine and I have tried GCC64 bit and
Visual Studio 2019 64 bit. The last two results are just ( -1 ). this is clearly over/underflow somehow so what changes are necessary.
I was in the opinion that stdint.h is cross-compiler/cross- platform
compliant.
[toc] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2021-06-13 23:27 +0100 |
| Message-ID | <GDvxI.19645$R591.15186@fx37.ams4> |
| In reply to | #161421 |
On 13/06/2021 23:08, SIMON wrote:
> What changes do I need to make to get the correct values for the last
> two items in this program:
>
>> #include <stdio.h>
>> #include <stdint.h>
>> #include <limits.h>
>>
>> int main()
>> {
>> printf("INT_MAX : %d\n", INT_MAX);
>> printf("INT_MIN : %d\n", INT_MIN);
>> printf("LONG_MAX : %ld\n", (long)LONG_MAX);
>> printf("LONG_MIN : %ld\n", (long)LONG_MIN);
>> printf("UINT_MAX : %u\n", (unsigned int)UINT_MAX);
>> printf("ULONG_MAX : %lu\n", (unsigned long)ULONG_MAX);
>> printf("USHRT_MAX : %d\n", (unsigned short)USHRT_MAX);
>> printf("\nFrom stdint.h: \n");
>> printf("INT8_MAX : %d\n", INT8_MAX);
>> printf("INT16_MAX : %d\n", INT16_MAX);
>> printf("INT32_MAX : %d\n", INT32_MAX);
>> printf("INT64_MAX : %lld\n", INT64_MAX);
>> printf("UINT8_MAX : %d\n", UINT16_MAX);
>> printf("UINT16_MAX : %d\n", UINT16_MAX);
>> printf("UINT32_MAX : %d\n", UINT32_MAX);
>> printf("UINT64_MAX : %lld\n", UINT64_MAX);
>> }
>
> I am using Windows 10 64 bit machine and I have tried GCC64 bit and
> Visual Studio 2019 64 bit. The last two results are just ( -1 ). this is
> clearly over/underflow somehow so what changes are necessary.
>
> I was in the opinion that stdint.h is cross-compiler/cross- platform
> compliant.
Try %ud and %ulld.
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2021-06-13 23:57 +0100 |
| Message-ID | <v3wxI.85192$_jR.41980@fx14.ams4> |
| In reply to | #161422 |
On 13/06/2021 23:27, Bart wrote:
> On 13/06/2021 23:08, SIMON wrote:
>> What changes do I need to make to get the correct values for the last
>> two items in this program:
>>
>>> #include <stdio.h>
>>> #include <stdint.h>
>>> #include <limits.h>
>>>
>>> int main()
>>> {
>>> printf("INT_MAX : %d\n", INT_MAX);
>>> printf("INT_MIN : %d\n", INT_MIN);
>>> printf("LONG_MAX : %ld\n", (long)LONG_MAX);
>>> printf("LONG_MIN : %ld\n", (long)LONG_MIN);
>>> printf("UINT_MAX : %u\n", (unsigned int)UINT_MAX);
>>> printf("ULONG_MAX : %lu\n", (unsigned long)ULONG_MAX);
>>> printf("USHRT_MAX : %d\n", (unsigned short)USHRT_MAX);
>>> printf("\nFrom stdint.h: \n");
>>> printf("INT8_MAX : %d\n", INT8_MAX);
>>> printf("INT16_MAX : %d\n", INT16_MAX);
>>> printf("INT32_MAX : %d\n", INT32_MAX);
>>> printf("INT64_MAX : %lld\n", INT64_MAX);
>>> printf("UINT8_MAX : %d\n", UINT16_MAX);
>>> printf("UINT16_MAX : %d\n", UINT16_MAX);
>>> printf("UINT32_MAX : %d\n", UINT32_MAX);
>>> printf("UINT64_MAX : %lld\n", UINT64_MAX);
>>> }
>>
>> I am using Windows 10 64 bit machine and I have tried GCC64 bit and
>> Visual Studio 2019 64 bit. The last two results are just ( -1 ). this
>> is clearly over/underflow somehow so what changes are necessary.
>>
>> I was in the opinion that stdint.h is cross-compiler/cross- platform
>> compliant.
>
>
> Try %ud and %ulld.
Huh. They should be %u and %llu (u is because they are unsigned).
Or you can display as hex using %X and $llX.
This should fine if running under Windows. For portable code, you really
need to use an ugly set of macros from stdint.h or inttypes.h, since the
correct formats vary betweeen Windows and Linux (eg. Linux might need
one 'l' rather than two, but I believe 'll' will work too).
If you just want to know the limits, you can also look inside stdint.h.
[toc] | [prev] | [next] | [standalone]
| From | Philipp Klaus Krause <pkk@spth.de> |
|---|---|
| Date | 2021-06-14 09:03 +0200 |
| Message-ID | <sa6v0v$4r0$1@solani.org> |
| In reply to | #161425 |
Am 14.06.21 um 00:57 schrieb Bart:
>
> This should fine if running under Windows. For portable code, you really
> need to use an ugly set of macros from stdint.h or inttypes.h, since the
> correct formats vary betweeen Windows and Linux (eg. Linux might need
> one 'l' rather than two, but I believe 'll' will work too).
The C23 standard from 2023 has the %w modifier:
printf("UINT64_MAX : %w64u\n", UINT64_MAX);
Philipp
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-06-14 01:23 -0700 |
| Message-ID | <87sg1kyhv7.fsf@nosuchdomain.example.com> |
| In reply to | #161429 |
Philipp Klaus Krause <pkk@spth.de> writes:
> Am 14.06.21 um 00:57 schrieb Bart:
>> This should fine if running under Windows. For portable code, you really
>> need to use an ugly set of macros from stdint.h or inttypes.h, since the
>> correct formats vary betweeen Windows and Linux (eg. Linux might need
>> one 'l' rather than two, but I believe 'll' will work too).
>
> The C23 standard from 2023 has the %w modifier:
>
> printf("UINT64_MAX : %w64u\n", UINT64_MAX);
Do you have a source for that? The latest draft I have (N2596,
Dec 11 2020) doesn't mention that.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Philipp Klaus Krause <pkk@spth.de> |
|---|---|
| Date | 2021-06-14 12:31 +0200 |
| Message-ID | <sa7b6a$b7n$2@solani.org> |
| In reply to | #161431 |
>> The C23 standard from 2023 has the %w modifier:
>>
>> printf("UINT64_MAX : %w64u\n", UINT64_MAX);
>
> Do you have a source for that? The latest draft I have (N2596,
> Dec 11 2020) doesn't mention that.
The proposal was N2680, which according to the meeting minutes N2690 is in.
Philipp
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2021-06-14 11:54 +0100 |
| Message-ID | <aAGxI.151628$co68.48603@fx03.ams4> |
| In reply to | #161429 |
On 14/06/2021 08:03, Philipp Klaus Krause wrote:
> Am 14.06.21 um 00:57 schrieb Bart:
>>
>> This should fine if running under Windows. For portable code, you really
>> need to use an ugly set of macros from stdint.h or inttypes.h, since the
>> correct formats vary betweeen Windows and Linux (eg. Linux might need
>> one 'l' rather than two, but I believe 'll' will work too).
>
> The C23 standard from 2023 has the %w modifier:
>
> printf("UINT64_MAX : %w64u\n", UINT64_MAX);
>
> Philipp
>
%w64u is not supported by msvcrt.dll yet.
However why are they still messing about with format codes? One change I
tried with my C compiler was to use a "%?" specifier which adapts itself
to whatever is being printed:
printf("UINT64_MAX/A : %llu\n", UINT64_MAX);
printf("UINT64_MAX/B : %w64u\n", UINT64_MAX);
printf("UINT64_MAX/C : %?\n", UINT64_MAX);
Output is:
UINT64_MAX/A : 18446744073709551615
UINT64_MAX/B : 64u
UINT64_MAX/C : 18446744073709551615
Of course, this is done inside the compiler and is only possible when a
format is a string literal; it does not change the library.
I can use this one format in the OP's program:
printf("INT_MAX : %?\n", INT_MAX);
printf("INT_MIN : %?\n", INT_MIN);
printf("LONG_MAX : %?\n", (long)LONG_MAX);
printf("LONG_MIN : %?\n", (long)LONG_MIN);
printf("UINT_MAX : %?\n", (unsigned int)UINT_MAX);
printf("ULONG_MAX : %?\n", (unsigned long)ULONG_MAX);
printf("USHRT_MAX : %?\n", (unsigned short)USHRT_MAX);
printf("\nFrom stdint.h: \n");
printf("INT8_MAX : %?\n", INT8_MAX);
printf("INT16_MAX : %?\n", INT16_MAX);
printf("INT32_MAX : %?\n", INT32_MAX);
printf("INT64_MAX : %?\n", INT64_MAX);
printf("UINT8_MAX : %?\n", UINT8_MAX); // Fixed FROM UINT16_MAX
printf("UINT16_MAX : %?\n", UINT16_MAX);
printf("UINT32_MAX : %?\n", UINT32_MAX);
printf("UINT64_MAX : %?\n", UINT64_MAX);
And the output is:
INT_MAX : 2147483647
INT_MIN : -2147483648
LONG_MAX : 2147483647
LONG_MIN : -2147483648
UINT_MAX : 4294967295
ULONG_MAX : 4294967295
USHRT_MAX : 65535
From stdint.h:
INT8_MAX : 127
INT16_MAX : 32767
INT32_MAX : 2147483647
INT64_MAX : 9223372036854775807
UINT8_MAX : 255
UINT16_MAX : 65535
UINT32_MAX : 4294967295
UINT64_MAX : 18446744073709551615
Who, in 2023 and beyond, still wants to muck around with format codes?!
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-06-13 18:34 -0400 |
| Message-ID | <sa615b$e1r$1@dont-email.me> |
| In reply to | #161421 |
On 6/13/21 6:08 PM, SIMON wrote:
> What changes do I need to make to get the correct values for the last
> two items in this program:
>
>> #include <stdio.h>
>> #include <stdint.h>
>> #include <limits.h>
#include <inttypes.h>
>> int main()
>> {
>> printf("INT_MAX : %d\n", INT_MAX);
>> printf("INT_MIN : %d\n", INT_MIN);
>> printf("LONG_MAX : %ld\n", (long)LONG_MAX);
>> printf("LONG_MIN : %ld\n", (long)LONG_MIN);
>> printf("UINT_MAX : %u\n", (unsigned int)UINT_MAX);
>> printf("ULONG_MAX : %lu\n", (unsigned long)ULONG_MAX);
>> printf("USHRT_MAX : %d\n", (unsigned short)USHRT_MAX);
>> printf("\nFrom stdint.h: \n");
>> printf("INT8_MAX : %d\n", INT8_MAX);
>> printf("INT16_MAX : %d\n", INT16_MAX);
>> printf("INT32_MAX : %d\n", INT32_MAX);
>> printf("INT64_MAX : %lld\n", INT64_MAX);
>> printf("UINT8_MAX : %d\n", UINT16_MAX);
>> printf("UINT16_MAX : %d\n", UINT16_MAX);
>> printf("UINT32_MAX : %d\n", UINT32_MAX);
>> printf("UINT64_MAX : %lld\n", UINT64_MAX);
You should not be using the "d" conversion specifier for unsigned types.
You should use "u", "o", "x" or "X" formats.
In general, you should not use explicit length specifiers (such as "h",
"hh", "l", and "ll") for the size-named types - there's no guaranteed
connection between the specifiers and the types. Instead, you should use
the print format macros from <inttypes.h>:
printf("INT8_MAX : %" PRId8 "\n", INT8_MAX);
printf("INT8_MAX : %" PRId16 "\n", INT16_MAX);
printf("INT8_MAX : %" PRId32 "\n", INT32_MAX);
printf("INT8_MAX : %" PRId64 "\n", INT64_MAX);
Assuming that you would actually have chosen the "u" conversion
specifier, you should use the following for the unsigned types. If you
would prefer, for instance, the "x" conversion specifier, change "u" to
"x" in the following macro names:
printf("UINT8_MAX : %" PRIu8 "\n", UINT8_MAX);
printf("UINT8_MAX : %" PRIu16 "\n", UINT16_MAX);
printf("UINT8_MAX : %" PRIu32 "\n", UINT32_MAX);
printf("UINT8_MAX : %" PRIu64 "\n", UINT64_MAX);
>> }
>
> I am using Windows 10 64 bit machine and I have tried GCC64 bit and
> Visual Studio 2019 64 bit. The last two results are just ( -1 ). this is clearly over/underflow somehow so what changes are necessary.
>
> I was in the opinion that stdint.h is cross-compiler/cross- platform
> compliant.
It is, when used correctly - which means, among other things, using the
print macros rather than explicit length specifiers in printf/scanf
family format strings. The exact-sized types are optional, but the
corresponding macros must be #defined and if (and only if) the
corresponding types are supported.
For maximum portability, you should avoid the exact-sized types and use
only int_fastN_t and int_leastN_t types, and only for the values of N
for which support for those types is mandatory: 8, 16, 32, and 64. In
practice, most people can ignore this advice.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2021-06-13 23:34 +0100 |
| Message-ID | <87h7i11jhx.fsf@bsb.me.uk> |
| In reply to | #161421 |
SIMON <invalid@invalid.invalid> writes:
> What changes do I need to make to get the correct values for the last
> two items in this program:
>
>> #include <stdio.h>
>> #include <stdint.h>
>> #include <limits.h>
>>
>> int main()
>> {
>> printf("INT_MAX : %d\n", INT_MAX);
>> printf("INT_MIN : %d\n", INT_MIN);
>> printf("LONG_MAX : %ld\n", (long)LONG_MAX);
>> printf("LONG_MIN : %ld\n", (long)LONG_MIN);
>> printf("UINT_MAX : %u\n", (unsigned int)UINT_MAX);
>> printf("ULONG_MAX : %lu\n", (unsigned long)ULONG_MAX);
>> printf("USHRT_MAX : %d\n", (unsigned short)USHRT_MAX);
None of these casts add anything.
(There are also LLONG_MIN/MAX and ULLONG_MAX which you can print using
%lld and %llu.)
>> printf("\nFrom stdint.h: \n");
>> printf("INT8_MAX : %d\n", INT8_MAX);
>> printf("INT16_MAX : %d\n", INT16_MAX);
>> printf("INT32_MAX : %d\n", INT32_MAX);
>> printf("INT64_MAX : %lld\n", INT64_MAX);
>> printf("UINT8_MAX : %d\n", UINT16_MAX);
>> printf("UINT16_MAX : %d\n", UINT16_MAX);
>> printf("UINT32_MAX : %d\n", UINT32_MAX);
>> printf("UINT64_MAX : %lld\n", UINT64_MAX);
All of these types have macros defined in inttypes.h that can be used to
print them. For example
printf("UINT64_MAX : %"PRIu64"\n", UINT64_MAX);
For maximum portability, you can't even assume that %d can be used for
INT32_MAX -- on a system where int is narrower than 32 bits, %d won't
work. Similarly, %d won't necessarily work even for UINT16_MAX. On a
system with a 16-bit int you would have to use %u. But all of these are
"fudges" to some extent.
The last two can be also fudged (for the sort of system you are likely
to be using) like this:
printf("UINT32_MAX : %u\n", UINT32_MAX);
printf("UINT64_MAX : %llu\n", UINT64_MAX);
but really, why fudge it? Use PRIu32 and PRIu64.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-06-13 17:48 -0700 |
| Message-ID | <87wnqxxoe3.fsf@nosuchdomain.example.com> |
| In reply to | #161421 |
SIMON <invalid@invalid.invalid> writes:
> What changes do I need to make to get the correct values for the last
> two items in this program:
>
>> #include <stdio.h>
>> #include <stdint.h>
>> #include <limits.h>
>>
>> int main()
>> {
>> printf("INT_MAX : %d\n", INT_MAX);
>> printf("INT_MIN : %d\n", INT_MIN);
>> printf("LONG_MAX : %ld\n", (long)LONG_MAX);
>> printf("LONG_MIN : %ld\n", (long)LONG_MIN);
>> printf("UINT_MAX : %u\n", (unsigned int)UINT_MAX);
>> printf("ULONG_MAX : %lu\n", (unsigned long)ULONG_MAX);
>> printf("USHRT_MAX : %d\n", (unsigned short)USHRT_MAX);
>> printf("\nFrom stdint.h: \n");
>> printf("INT8_MAX : %d\n", INT8_MAX);
>> printf("INT16_MAX : %d\n", INT16_MAX);
>> printf("INT32_MAX : %d\n", INT32_MAX);
>> printf("INT64_MAX : %lld\n", INT64_MAX);
>> printf("UINT8_MAX : %d\n", UINT16_MAX);
>> printf("UINT16_MAX : %d\n", UINT16_MAX);
>> printf("UINT32_MAX : %d\n", UINT32_MAX);
>> printf("UINT64_MAX : %lld\n", UINT64_MAX);
>> }
>
> I am using Windows 10 64 bit machine and I have tried GCC64 bit and
> Visual Studio 2019 64 bit. The last two results are just ( -1 ). this
> is clearly over/underflow somehow so what changes are necessary.
>
> I was in the opinion that stdint.h is cross-compiler/cross- platform
> compliant.
It is -- but none of the exact-width types are guaranteed to exist
(though the 8, 16, 32, and 64 bit ones almost certainly will on typical
systems).
<inttypes.h> provides macros that expand to appropriate format strings.
<inttypes.h> includes <stdint.h>, so you don't need to include both,
though you can.
Using the macros:
#include <stdio.h>
// #include <stdint.h>
#include <inttypes.h>
#include <limits.h>
int main(void) {
printf("INT_MAX : %d\n", INT_MAX);
printf("INT_MIN : %d\n", INT_MIN);
printf("LONG_MAX : %ld\n", LONG_MAX);
printf("LONG_MIN : %ld\n", LONG_MIN);
printf("UINT_MAX : %u\n", UINT_MAX);
printf("ULONG_MAX : %lu\n", ULONG_MAX);
printf("USHRT_MAX : %u\n", (unsigned)USHRT_MAX);
printf("\nFrom stdint.h: \n");
printf("INT8_MAX : %" PRId8 "\n", INT8_MAX);
printf("INT16_MAX : %" PRId16 "\n", INT16_MAX);
printf("INT32_MAX : %" PRId32 "\n", INT32_MAX);
printf("INT64_MAX : %" PRId64 "\n", INT64_MAX);
printf("UINT8_MAX : %" PRIu8 "\n", UINT16_MAX);
printf("UINT16_MAX : %" PRIu16 "\n", UINT16_MAX);
printf("UINT32_MAX : %" PRIu32 "\n", UINT32_MAX);
printf("UINT64_MAX : %" PRIu64 "\n", UINT64_MAX);
}
Most of the casts in your original program are unnecessary, since the
expressions are already of the type you were casting them to. But
unsigned short could promote either to signed int or to unsigned int,
depending on their ranges, so converting to unsigned and using "%u" is
appropriate. In general, when passed to a variadic function like
printf, an argument of an integer type narrower than int is promoted to
int if type's range fits in int, to unsigned int otherwise.
An alternative, if you don't want to remember or look up all those
macros, is to convert to a type that's known to be wide enough.
long long is guaranteed to be at least 64 bits (and is almost always
exactly 64 bits), so this might be simpler:
#include <stdio.h>
#include <stdint.h>
#include <limits.h>
int main(void) {
printf("INT_MAX : %d\n", INT_MAX);
printf("INT_MIN : %d\n", INT_MIN);
printf("LONG_MAX : %ld\n", LONG_MAX);
printf("LONG_MIN : %ld\n", LONG_MIN);
printf("UINT_MAX : %u\n", UINT_MAX);
printf("ULONG_MAX : %lu\n", ULONG_MAX);
printf("USHRT_MAX : %u\n", (unsigned)USHRT_MAX);
printf("\nFrom stdint.h : \n");
printf("INT8_MAX : %lld\n", (long long)INT8_MAX);
printf("INT16_MAX : %lld\n", (long long)INT16_MAX);
printf("INT32_MAX : %lld\n", (long long)INT32_MAX);
printf("INT64_MAX : %lld\n", (long long)INT64_MAX);
printf("UINT8_MAX : %llu\n", (unsigned long long)UINT16_MAX);
printf("UINT16_MAX : %llu\n", (unsigned long long)UINT16_MAX);
printf("UINT32_MAX : %llu\n", (unsigned long long)UINT32_MAX);
printf("UINT64_MAX : %llu\n", (unsigned long long)UINT64_MAX);
}
There's some performance cost relative to the type-specific format
macros, but printf itself is far more expensive than a few integer type
conversions.
If you have an integer type that might possibly be wider than long
long (which is unlikely in practice), you can convert to intmax_t
or uintmax_t and use "%jd" or "%ju". That might be overkill if you
don't really need 100% guarantee portability.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Philipp Klaus Krause <pkk@spth.de> |
|---|---|
| Date | 2021-06-14 09:09 +0200 |
| Message-ID | <sa6vaf$4r0$2@solani.org> |
| In reply to | #161426 |
Am 14.06.21 um 02:48 schrieb Keith Thompson: > > If you have an integer type that might possibly be wider than long > long (which is unlikely in practice), you can convert to intmax_t > or uintmax_t and use "%jd" or "%ju". That might be overkill if you > don't really need 100% guarantee portability. > And there is the real risk of intmax_t being removed from a future standard, which is very, very unlikely to ever happen to long long. Philipp
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-06-14 01:24 -0700 |
| Message-ID | <87o8c8yhtx.fsf@nosuchdomain.example.com> |
| In reply to | #161430 |
Philipp Klaus Krause <pkk@spth.de> writes:
> Am 14.06.21 um 02:48 schrieb Keith Thompson:
>> If you have an integer type that might possibly be wider than long
>> long (which is unlikely in practice), you can convert to intmax_t
>> or uintmax_t and use "%jd" or "%ju". That might be overkill if you
>> don't really need 100% guarantee portability.
>
> And there is the real risk of intmax_t being removed from a future
> standard, which is very, very unlikely to ever happen to long long.
I doubt that there's much risk of that. I can imagine its semantics
being changed, but removing it would break existing code.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Philipp Klaus Krause <pkk@spth.de> |
|---|---|
| Date | 2021-06-14 12:30 +0200 |
| Message-ID | <sa7b4i$b7n$1@solani.org> |
| In reply to | #161432 |
>> And there is the real risk of intmax_t being removed from a future >> standard, which is very, very unlikely to ever happen to long long. > > I doubt that there's much risk of that. I can imagine its semantics > being changed, but removing it would break existing code. > The problem with intmax_t: It needs to be the widest type, so it needs to grow when y type is added. That breaks the ABI. There was a WG14 straw poll opting for full removal, but no wording had been proposed at that time, and no wording has come up so far. However, N2548 has changed some functions to use different types instead: Functions new in C23 have been changed to use whatever other type was most appropriate. Older functions have been changed to long long, since apparently practically intmax_t was the same as long long, so this change preserves the ABI. Philipp
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2021-06-24 10:31 -0700 |
| Message-ID | <86bl7vb24m.fsf@linuxsc.com> |
| In reply to | #161426 |
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
[... on printing various integer types ...]
> Using the macros:
>
> #include <stdio.h>
> // #include <stdint.h>
> #include <inttypes.h>
> #include <limits.h>
>
> int main(void) {
> printf("INT_MAX : %d\n", INT_MAX);
> printf("INT_MIN : %d\n", INT_MIN);
> printf("LONG_MAX : %ld\n", LONG_MAX);
> printf("LONG_MIN : %ld\n", LONG_MIN);
> printf("UINT_MAX : %u\n", UINT_MAX);
> printf("ULONG_MAX : %lu\n", ULONG_MAX);
> printf("USHRT_MAX : %u\n", (unsigned)USHRT_MAX);
The cast in the last line is not needed.
> printf("\nFrom stdint.h: \n");
> printf("INT8_MAX : %" PRId8 "\n", INT8_MAX);
> printf("INT16_MAX : %" PRId16 "\n", INT16_MAX);
> printf("INT32_MAX : %" PRId32 "\n", INT32_MAX);
> printf("INT64_MAX : %" PRId64 "\n", INT64_MAX);
> printf("UINT8_MAX : %" PRIu8 "\n", UINT16_MAX);
> printf("UINT16_MAX : %" PRIu16 "\n", UINT16_MAX);
> printf("UINT32_MAX : %" PRIu32 "\n", UINT32_MAX);
> printf("UINT64_MAX : %" PRIu64 "\n", UINT64_MAX);
> }
>
> Most of the casts in your original program are unnecessary, since
> the expressions are already of the type you were casting them to.
> But unsigned short could promote either to signed int or to
> unsigned int, depending on their ranges, so converting to unsigned
> and using "%u" is appropriate. In general, when passed to a
> variadic function like printf, an argument of an integer type
> narrower than int is promoted to int if type's range fits in int,
> to unsigned int otherwise.
The description of how type promotion works is right, however a
cast is still not needed there. The reason is that values given
as variadic arguments are allowed to be the corresponding signed
or unsigned version of the type used to get the value, and that
will work as long as the value is in the set of values common to
both types. If an unsigned short promotes to int, then its value
is guaranteed to be in the set of values representable by both
int and unsigned int, and hence using %u for an uncasted unsigned
short is always safe.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-06-24 11:28 -0700 |
| Message-ID | <874kdnw20s.fsf@nosuchdomain.example.com> |
| In reply to | #161482 |
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>
> [... on printing various integer types ...]
>
>> Using the macros:
>>
>> #include <stdio.h>
>> // #include <stdint.h>
>> #include <inttypes.h>
>> #include <limits.h>
>>
>> int main(void) {
>> printf("INT_MAX : %d\n", INT_MAX);
>> printf("INT_MIN : %d\n", INT_MIN);
>> printf("LONG_MAX : %ld\n", LONG_MAX);
>> printf("LONG_MIN : %ld\n", LONG_MIN);
>> printf("UINT_MAX : %u\n", UINT_MAX);
>> printf("ULONG_MAX : %lu\n", ULONG_MAX);
>> printf("USHRT_MAX : %u\n", (unsigned)USHRT_MAX);
>
> The cast in the last line is not needed.
>
>> printf("\nFrom stdint.h: \n");
>> printf("INT8_MAX : %" PRId8 "\n", INT8_MAX);
>> printf("INT16_MAX : %" PRId16 "\n", INT16_MAX);
>> printf("INT32_MAX : %" PRId32 "\n", INT32_MAX);
>> printf("INT64_MAX : %" PRId64 "\n", INT64_MAX);
>> printf("UINT8_MAX : %" PRIu8 "\n", UINT16_MAX);
>> printf("UINT16_MAX : %" PRIu16 "\n", UINT16_MAX);
>> printf("UINT32_MAX : %" PRIu32 "\n", UINT32_MAX);
>> printf("UINT64_MAX : %" PRIu64 "\n", UINT64_MAX);
>> }
>>
>> Most of the casts in your original program are unnecessary, since
>> the expressions are already of the type you were casting them to.
>> But unsigned short could promote either to signed int or to
>> unsigned int, depending on their ranges, so converting to unsigned
>> and using "%u" is appropriate. In general, when passed to a
>> variadic function like printf, an argument of an integer type
>> narrower than int is promoted to int if type's range fits in int,
>> to unsigned int otherwise.
>
> The description of how type promotion works is right, however a
> cast is still not needed there. The reason is that values given
> as variadic arguments are allowed to be the corresponding signed
> or unsigned version of the type used to get the value, and that
> will work as long as the value is in the set of values common to
> both types. If an unsigned short promotes to int, then its value
> is guaranteed to be in the set of values representable by both
> int and unsigned int, and hence using %u for an uncasted unsigned
> short is always safe.
My reading of the standard is that that's certainly the intent, but
it's not quite stated explicitly.
N1570 6.5.2.2 makes a similar guarantee for calls to a function defined
without a prototype.
7.16.1.1 makes the same guarantee for arguments to the va_arg macro,
which makes it clear that printf("%u\n", 1) is *supposed* to work, but I
don't see a guarantee that the call itself (which happens before va_arg
is invoked -- assuming printf even uses va_arg) has defined behavior.
Or I'm missing something.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2021-07-11 02:49 -0700 |
| Message-ID | <86sg0l6uza.fsf@linuxsc.com> |
| In reply to | #161484 |
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>
>> [... on printing various integer types ...]
>>
>>> Using the macros:
>>>
>>> #include <stdio.h>
>>> // #include <stdint.h>
>>> #include <inttypes.h>
>>> #include <limits.h>
>>>
>>> int main(void) {
>>> printf("INT_MAX : %d\n", INT_MAX);
>>> printf("INT_MIN : %d\n", INT_MIN);
>>> printf("LONG_MAX : %ld\n", LONG_MAX);
>>> printf("LONG_MIN : %ld\n", LONG_MIN);
>>> printf("UINT_MAX : %u\n", UINT_MAX);
>>> printf("ULONG_MAX : %lu\n", ULONG_MAX);
>>> printf("USHRT_MAX : %u\n", (unsigned)USHRT_MAX);
>>
>> The cast in the last line is not needed.
>>
>>> printf("\nFrom stdint.h: \n");
>>> printf("INT8_MAX : %" PRId8 "\n", INT8_MAX);
>>> printf("INT16_MAX : %" PRId16 "\n", INT16_MAX);
>>> printf("INT32_MAX : %" PRId32 "\n", INT32_MAX);
>>> printf("INT64_MAX : %" PRId64 "\n", INT64_MAX);
>>> printf("UINT8_MAX : %" PRIu8 "\n", UINT16_MAX);
>>> printf("UINT16_MAX : %" PRIu16 "\n", UINT16_MAX);
>>> printf("UINT32_MAX : %" PRIu32 "\n", UINT32_MAX);
>>> printf("UINT64_MAX : %" PRIu64 "\n", UINT64_MAX);
>>> }
>>>
>>> Most of the casts in your original program are unnecessary, since
>>> the expressions are already of the type you were casting them to.
>>> But unsigned short could promote either to signed int or to
>>> unsigned int, depending on their ranges, so converting to unsigned
>>> and using "%u" is appropriate. In general, when passed to a
>>> variadic function like printf, an argument of an integer type
>>> narrower than int is promoted to int if type's range fits in int,
>>> to unsigned int otherwise.
>>
>> The description of how type promotion works is right, however a
>> cast is still not needed there. The reason is that values given
>> as variadic arguments are allowed to be the corresponding signed
>> or unsigned version of the type used to get the value, and that
>> will work as long as the value is in the set of values common to
>> both types. If an unsigned short promotes to int, then its value
>> is guaranteed to be in the set of values representable by both
>> int and unsigned int, and hence using %u for an uncasted unsigned
>> short is always safe.
>
> My reading of the standard is that that's certainly the intent, but
> it's not quite stated explicitly.
>
> N1570 6.5.2.2 makes a similar guarantee for calls to a function defined
> without a prototype.
>
> 7.16.1.1 makes the same guarantee for arguments to the va_arg macro,
> which makes it clear that printf("%u\n", 1) is *supposed* to work, but I
> don't see a guarantee that the call itself (which happens before va_arg
> is invoked -- assuming printf even uses va_arg) has defined behavior.
>
> Or I'm missing something.
I wrote a long reply to Ben Bacarisse in this same thread, you
may want to read that reply in addition to what I write here.
Basically the question boils down to what is meant by the
somewhat vague phrase "the correct type". I believe that phrase
is meant to refer to the rules of 7.16.1.1. If you want to say
there's an ambiguity about what is meant, certainly I could agree
with that. For purposes of posting in comp.lang.c, my usual rule
is to judge the language according to what meaning is intended,
and since here we are in agreement about what is intended here we
are not in conflict. Whether the C standard "actually says" that
the va_arg rules apply to *printf functions is, I think, not
an answerable question, and in any case not really a useful
question for purposes of comp.lang.c. I am glad we agree about
what rule is intended, and IMO that is really all that matters
for the present discussion.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-07-11 15:30 -0700 |
| Message-ID | <87mtqs5vre.fsf@nosuchdomain.example.com> |
| In reply to | #161872 |
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>> [... on printing various integer types ...]
>>>
>>>> Using the macros:
>>>>
>>>> #include <stdio.h>
>>>> // #include <stdint.h>
>>>> #include <inttypes.h>
>>>> #include <limits.h>
>>>>
>>>> int main(void) {
>>>> printf("INT_MAX : %d\n", INT_MAX);
>>>> printf("INT_MIN : %d\n", INT_MIN);
>>>> printf("LONG_MAX : %ld\n", LONG_MAX);
>>>> printf("LONG_MIN : %ld\n", LONG_MIN);
>>>> printf("UINT_MAX : %u\n", UINT_MAX);
>>>> printf("ULONG_MAX : %lu\n", ULONG_MAX);
>>>> printf("USHRT_MAX : %u\n", (unsigned)USHRT_MAX);
>>>
>>> The cast in the last line is not needed.
>>>
>>>> printf("\nFrom stdint.h: \n");
>>>> printf("INT8_MAX : %" PRId8 "\n", INT8_MAX);
>>>> printf("INT16_MAX : %" PRId16 "\n", INT16_MAX);
>>>> printf("INT32_MAX : %" PRId32 "\n", INT32_MAX);
>>>> printf("INT64_MAX : %" PRId64 "\n", INT64_MAX);
>>>> printf("UINT8_MAX : %" PRIu8 "\n", UINT16_MAX);
>>>> printf("UINT16_MAX : %" PRIu16 "\n", UINT16_MAX);
>>>> printf("UINT32_MAX : %" PRIu32 "\n", UINT32_MAX);
>>>> printf("UINT64_MAX : %" PRIu64 "\n", UINT64_MAX);
>>>> }
>>>>
>>>> Most of the casts in your original program are unnecessary, since
>>>> the expressions are already of the type you were casting them to.
>>>> But unsigned short could promote either to signed int or to
>>>> unsigned int, depending on their ranges, so converting to unsigned
>>>> and using "%u" is appropriate. In general, when passed to a
>>>> variadic function like printf, an argument of an integer type
>>>> narrower than int is promoted to int if type's range fits in int,
>>>> to unsigned int otherwise.
>>>
>>> The description of how type promotion works is right, however a
>>> cast is still not needed there. The reason is that values given
>>> as variadic arguments are allowed to be the corresponding signed
>>> or unsigned version of the type used to get the value, and that
>>> will work as long as the value is in the set of values common to
>>> both types. If an unsigned short promotes to int, then its value
>>> is guaranteed to be in the set of values representable by both
>>> int and unsigned int, and hence using %u for an uncasted unsigned
>>> short is always safe.
>>
>> My reading of the standard is that that's certainly the intent, but
>> it's not quite stated explicitly.
>>
>> N1570 6.5.2.2 makes a similar guarantee for calls to a function defined
>> without a prototype.
>>
>> 7.16.1.1 makes the same guarantee for arguments to the va_arg macro,
>> which makes it clear that printf("%u\n", 1) is *supposed* to work, but I
>> don't see a guarantee that the call itself (which happens before va_arg
>> is invoked -- assuming printf even uses va_arg) has defined behavior.
>>
>> Or I'm missing something.
>
> I wrote a long reply to Ben Bacarisse in this same thread, you
> may want to read that reply in addition to what I write here.
>
> Basically the question boils down to what is meant by the
> somewhat vague phrase "the correct type". I believe that phrase
> is meant to refer to the rules of 7.16.1.1. If you want to say
> there's an ambiguity about what is meant, certainly I could agree
> with that. For purposes of posting in comp.lang.c, my usual rule
> is to judge the language according to what meaning is intended,
> and since here we are in agreement about what is intended here we
> are not in conflict. Whether the C standard "actually says" that
> the va_arg rules apply to *printf functions is, I think, not
> an answerable question, and in any case not really a useful
> question for purposes of comp.lang.c. I am glad we agree about
> what rule is intended, and IMO that is really all that matters
> for the present discussion.
I mostly agree, but I disagree with your statement about the va_arg
rules applying to *printf.
The standard doesn't say that the *printf functions use va_arg. The
question of whether the standard *actually says* that va_arg rules apply
to *printf functions is, I think, answerable, and the answer is no.
Whether that matters is another question, but surely a question about
whether the standard says something can be resolved by reading the
standard.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2021-07-16 03:33 -0700 |
| Message-ID | <86h7gu7dki.fsf@linuxsc.com> |
| In reply to | #161879 |
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>
>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>
>>>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>>> [... on printing various integer types ...]
>>>>
>>>>> Using the macros:
>>>>>
>>>>> #include <stdio.h>
>>>>> // #include <stdint.h>
>>>>> #include <inttypes.h>
>>>>> #include <limits.h>
>>>>>
>>>>> int main(void) {
>>>>> printf("INT_MAX : %d\n", INT_MAX);
>>>>> printf("INT_MIN : %d\n", INT_MIN);
>>>>> printf("LONG_MAX : %ld\n", LONG_MAX);
>>>>> printf("LONG_MIN : %ld\n", LONG_MIN);
>>>>> printf("UINT_MAX : %u\n", UINT_MAX);
>>>>> printf("ULONG_MAX : %lu\n", ULONG_MAX);
>>>>> printf("USHRT_MAX : %u\n", (unsigned)USHRT_MAX);
>>>>
>>>> The cast in the last line is not needed.
>>>>
>>>>> printf("\nFrom stdint.h: \n");
>>>>> printf("INT8_MAX : %" PRId8 "\n", INT8_MAX);
>>>>> printf("INT16_MAX : %" PRId16 "\n", INT16_MAX);
>>>>> printf("INT32_MAX : %" PRId32 "\n", INT32_MAX);
>>>>> printf("INT64_MAX : %" PRId64 "\n", INT64_MAX);
>>>>> printf("UINT8_MAX : %" PRIu8 "\n", UINT16_MAX);
>>>>> printf("UINT16_MAX : %" PRIu16 "\n", UINT16_MAX);
>>>>> printf("UINT32_MAX : %" PRIu32 "\n", UINT32_MAX);
>>>>> printf("UINT64_MAX : %" PRIu64 "\n", UINT64_MAX);
>>>>> }
>>>>>
>>>>> Most of the casts in your original program are unnecessary, since
>>>>> the expressions are already of the type you were casting them to.
>>>>> But unsigned short could promote either to signed int or to
>>>>> unsigned int, depending on their ranges, so converting to unsigned
>>>>> and using "%u" is appropriate. In general, when passed to a
>>>>> variadic function like printf, an argument of an integer type
>>>>> narrower than int is promoted to int if type's range fits in int,
>>>>> to unsigned int otherwise.
>>>>
>>>> The description of how type promotion works is right, however a
>>>> cast is still not needed there. The reason is that values given
>>>> as variadic arguments are allowed to be the corresponding signed
>>>> or unsigned version of the type used to get the value, and that
>>>> will work as long as the value is in the set of values common to
>>>> both types. If an unsigned short promotes to int, then its value
>>>> is guaranteed to be in the set of values representable by both
>>>> int and unsigned int, and hence using %u for an uncasted unsigned
>>>> short is always safe.
>>>
>>> My reading of the standard is that that's certainly the intent, but
>>> it's not quite stated explicitly.
>>>
>>> N1570 6.5.2.2 makes a similar guarantee for calls to a function defined
>>> without a prototype.
>>>
>>> 7.16.1.1 makes the same guarantee for arguments to the va_arg macro,
>>> which makes it clear that printf("%u\n", 1) is *supposed* to work, but I
>>> don't see a guarantee that the call itself (which happens before va_arg
>>> is invoked -- assuming printf even uses va_arg) has defined behavior.
>>>
>>> Or I'm missing something.
>>
>> I wrote a long reply to Ben Bacarisse in this same thread, you
>> may want to read that reply in addition to what I write here.
>>
>> Basically the question boils down to what is meant by the
>> somewhat vague phrase "the correct type". I believe that phrase
>> is meant to refer to the rules of 7.16.1.1. If you want to say
>> there's an ambiguity about what is meant, certainly I could agree
>> with that. For purposes of posting in comp.lang.c, my usual rule
>> is to judge the language according to what meaning is intended,
>> and since here we are in agreement about what is intended here we
>> are not in conflict. Whether the C standard "actually says" that
>> the va_arg rules apply to *printf functions is, I think, not
>> an answerable question, and in any case not really a useful
>> question for purposes of comp.lang.c. I am glad we agree about
>> what rule is intended, and IMO that is really all that matters
>> for the present discussion.
>
> I mostly agree, but I disagree with your statement about the va_arg
> rules applying to *printf.
>
> The standard doesn't say that the *printf functions use va_arg. The
> question of whether the standard *actually says* that va_arg rules
> apply to *printf functions is, I think, answerable, and the answer
> is no.
>
> Whether that matters is another question, but surely a question
> about whether the standard says something can be resolved by reading
> the standard.
I think you misunderstood what I was saying. There is no
question about what words are present. What the words mean is
another story. In many cases if not most cases the meaning
of sentences written in English is at least partly subjective.
That is the case here. To talk about what the words "actually
say" is to talk about meaning, and here the meaning is
ambiguous. The phrase "the correct type" is not well-defined.
In fact, since it has not been given an explicit definition,
someone might conclude that a *printf format that needs any
arguments at all will necessarily lead to undefined behavior.
I think you want to ascribe some sort of objective meaning
to the text, but the use of the undefined phrase "the correct
type" makes that impossible.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-07-16 12:31 -0700 |
| Message-ID | <87a6mm2gzj.fsf@nosuchdomain.example.com> |
| In reply to | #161929 |
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
[...]
>>> Basically the question boils down to what is meant by the
>>> somewhat vague phrase "the correct type". I believe that phrase
>>> is meant to refer to the rules of 7.16.1.1. If you want to say
>>> there's an ambiguity about what is meant, certainly I could agree
>>> with that. For purposes of posting in comp.lang.c, my usual rule
>>> is to judge the language according to what meaning is intended,
>>> and since here we are in agreement about what is intended here we
>>> are not in conflict. Whether the C standard "actually says" that
>>> the va_arg rules apply to *printf functions is, I think, not
>>> an answerable question, and in any case not really a useful
>>> question for purposes of comp.lang.c. I am glad we agree about
>>> what rule is intended, and IMO that is really all that matters
>>> for the present discussion.
>>
>> I mostly agree, but I disagree with your statement about the va_arg
>> rules applying to *printf.
>>
>> The standard doesn't say that the *printf functions use va_arg. The
>> question of whether the standard *actually says* that va_arg rules
>> apply to *printf functions is, I think, answerable, and the answer
>> is no.
>>
>> Whether that matters is another question, but surely a question
>> about whether the standard says something can be resolved by reading
>> the standard.
>
> I think you misunderstood what I was saying. There is no
> question about what words are present. What the words mean is
> another story. In many cases if not most cases the meaning
> of sentences written in English is at least partly subjective.
> That is the case here. To talk about what the words "actually
> say" is to talk about meaning, and here the meaning is
> ambiguous. The phrase "the correct type" is not well-defined.
> In fact, since it has not been given an explicit definition,
> someone might conclude that a *printf format that needs any
> arguments at all will necessarily lead to undefined behavior.
> I think you want to ascribe some sort of objective meaning
> to the text, but the use of the undefined phrase "the correct
> type" makes that impossible.
I think it's not so much misunderstanding as disagreement.
You wrote:
Whether the C standard "actually says" that the va_arg rules apply
to *printf functions is, I think, not an answerable question, and in
any case not really a useful question for purposes of comp.lang.c.
I simply disagree. It is an answerable question, and the answer is no;
the standard does not say that anywhere. It provides <stdarg.h> as *a*
mechanism for implementing variadic functions, and specifies the rules
that apply when va_arg is used, but it simply does not say that printf
is implemented using va_arg or that it follows the rules specified for
va_arg. A footnote says "The macros defined in the <stdarg.h> header
(7.16) may be used to access arguments that correspond to the
ellipsis.", which clearly implies the possibility of other mechanisms.
If it said that, there would be words to that effect. There
aren't. (Of course I'm open to correction if I'm missed something.)
As for "the correct type", I suggest that that phrase is inconsistent
with there being more than one correct type. The phrase "the correct
type" is not rigorously defined, but it is unambiguous that it refers to
one type. int and unsigned int are two distinct types; it is not
possible that they can both qualify as "the correct type". If it had
said "a correct type", that would leave open the possibility that either
int or unsigned int might be correct as an argument corresponding to
"%d", for example.
You see ambiguity in the words used in the standard that, as I read it,
just isn't there.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2021-09-30 07:07 -0700 |
| Message-ID | <86h7e2tawh.fsf@linuxsc.com> |
| In reply to | #161940 |
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes: > Tim Rentsch <tr.17687@z991.linuxsc.com> writes: >> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes: >>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes: > [...] >>>> Basically the question boils down to what is meant by the >>>> somewhat vague phrase "the correct type". I believe that phrase >>>> is meant to refer to the rules of 7.16.1.1. If you want to say >>>> there's an ambiguity about what is meant, certainly I could agree >>>> with that. For purposes of posting in comp.lang.c, my usual rule >>>> is to judge the language according to what meaning is intended, >>>> and since here we are in agreement about what is intended here we >>>> are not in conflict. Whether the C standard "actually says" that >>>> the va_arg rules apply to *printf functions is, I think, not >>>> an answerable question, and in any case not really a useful >>>> question for purposes of comp.lang.c. I am glad we agree about >>>> what rule is intended, and IMO that is really all that matters >>>> for the present discussion. >>> >>> I mostly agree, but I disagree with your statement about the va_arg >>> rules applying to *printf. >>> >>> The standard doesn't say that the *printf functions use va_arg. The >>> question of whether the standard *actually says* that va_arg rules >>> apply to *printf functions is, I think, answerable, and the answer >>> is no. >>> >>> Whether that matters is another question, but surely a question >>> about whether the standard says something can be resolved by reading >>> the standard. >> >> I think you misunderstood what I was saying. There is no >> question about what words are present. What the words mean is >> another story. In many cases if not most cases the meaning >> of sentences written in English is at least partly subjective. >> That is the case here. To talk about what the words "actually >> say" is to talk about meaning, and here the meaning is >> ambiguous. The phrase "the correct type" is not well-defined. >> In fact, since it has not been given an explicit definition, >> someone might conclude that a *printf format that needs any >> arguments at all will necessarily lead to undefined behavior. >> I think you want to ascribe some sort of objective meaning >> to the text, but the use of the undefined phrase "the correct >> type" makes that impossible. > > I think it's not so much misunderstanding as disagreement. > > You wrote: > > Whether the C standard "actually says" that the va_arg rules apply > to *printf functions is, I think, not an answerable question, and in > any case not really a useful question for purposes of comp.lang.c. > > I simply disagree. It is an answerable question, [...] The question I am considering does not have an objective answer. Did you not understand that?
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.c
csiph-web