From: Laszlo Ersek <lersek@redhat.com>
To: "Cohen, Eugene" <eugene@hp.com>
Cc: "edk2-devel@lists.01.org" <edk2-devel@ml01.01.org>,
"Kinney, Michael D" <michael.d.kinney@intel.com>,
Alexei Fedorov <Alexei.Fedorov@arm.com>
Subject: Re: What is the right way to print a UINTN?
Date: Tue, 27 Sep 2016 16:30:04 +0200 [thread overview]
Message-ID: <bb4c6e4a-0ed9-3218-06e3-034feb1a1c60@redhat.com> (raw)
In-Reply-To: <AT5PR84MB02910FADA0BFA8F5C5E7E96CB4CC0@AT5PR84MB0291.NAMPRD84.PROD.OUTLOOK.COM>
On 09/27/16 14:29, Cohen, Eugene wrote:
> Laszlo,
>
>> I print INTN / UINTN values with:
>> - casting them unconditionally to INT64 / UINT64,
>> - printing the converted values with the matching conversion
>> specifiers,
>> such as %Ld (for INT64) and %Lu or %Lx (for UINT64).
>>
>> This solution requires a bit more typing, and it is a bit pessimistic
>> for 32-bit builds. On the positive side, it is robust / portable, and
>> completely valid C.
>>
>> It is inspired by the standard C types intmax_t / uintmax_t. If you
>> write portable C code and want to print a value of some integer type,
>> where the spec only states "signed" or "unsigned integer type", but
>> the
>> actual type is either implementation defined or unspecified,
>> converting
>> the value to intmax_t / uintmax_t, and then printing it with %jd vs. %ju
>> / %jx, is safe.
>
> Thanks - this makes sense. If this methodology is consistent with
> standard C then perhaps it's the best compromise even if it's messy
> to read.
>
> From a consistency perspective I see a lot of variation in usage -
> often UINTNs are printed with %x / %d (technically it should be %u
> but this is a common error - just compare the number of occurrences
> of %u in MdeModulePkg versus %d).
Printing UINTN with %x *or* with %d are equally bugs.
For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
work most of the time).
For Ia32 / ARM builds, %x is not an actual bug, just a portability one /
code smell. And %d may or may not be an actual bug, dependent on the
value being printed.
> This means that the caller is
> expecting that the value will never exceed 2^32-1 on 64-bit systems
> since we are doing 64-bit to 32-bit truncation through the cast in
> the VA_ARG macro.
I think that the specifics why printing UINTN with %x (or %d) happens to
work on X64 / AARCH64, for a subset of the UINTN values, are not
interesting. As far as I'm concerned, even the argument *sizes* are
wrong, which might as well lead to incorrect accesses to the stack.
> I'm concerned that this requires the developer to
> know the constraints on the value in all circumstances which seems
> dubious - after all that's why we have types in the first place, so
> the tools can help us do the right thing.
The developer is first and foremost required to match the conversion
specifiers to the types of the arguments being passed. For UINTN there
is no dedicated conversion specifier, hence my recommendation for the
casting.
> I'm envisioning having to create a slide in the future for UEFI
> training about the proper use of UINTNs and describing "If you think
> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
> about it" and it makes me squirm.
It makes me squirm too. I think the slide should recommend the casting
that I proposed. ;) "There is no conversion specifier dedicated to
UINTN; the portable way to print it is to cast it to UINT64, then print
it with %Lx."
Thanks
Laszlo
next prev parent reply other threads:[~2016-09-27 14:30 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-26 13:46 What is the right way to print a UINTN? Cohen, Eugene
2016-09-26 14:39 ` Alexei Fedorov
2016-09-26 15:31 ` Laszlo Ersek
2016-09-27 12:29 ` Cohen, Eugene
2016-09-27 14:30 ` Laszlo Ersek [this message]
2016-09-27 16:03 ` Cohen, Eugene
2016-09-27 16:31 ` Laszlo Ersek
2016-09-27 16:47 ` Andrew Fish
2016-09-27 17:14 ` Brian J. Johnson
2016-09-27 18:31 ` Laszlo Ersek
2016-09-27 20:27 ` Kinney, Michael D
2016-09-27 17:27 ` Kinney, Michael D
2016-09-27 17:46 ` Andrew Fish
2016-09-27 18:20 ` Kinney, Michael D
2016-09-27 19:28 ` Cohen, Eugene
2016-09-27 20:10 ` Kinney, Michael D
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=bb4c6e4a-0ed9-3218-06e3-034feb1a1c60@redhat.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox