Why doesn't the '+' sign work with printf for unsigned values?
Asked Answered
D

3

3

I just wrote and ran following program. This just gave an unexpected output without + sign printed to U...MAX.

#include <limists.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
    // ...
    printf("LLONG_MIN:  %+lli\n", LLONG_MIN);
    printf("LLONG_MAX:  %+lld\n", LLONG_MAX);
    printf("ULLONG_MAX: %+llu\n", ULLONG_MAX);
    return EXIT_SUCCESS;
}

And I got this:

CHAR_BIT:   8
SCHAR_MIN:  -128
SCHAR_MAX:  +127
UCHAR_MAX:  255
SHRT_MIN:   -32768
SHRT_MAX:   +32767
USHRT_MAX:  65535
INT_MIN:    -2147483648
INT_MAX:    +2147483647
UINT_MAX:   4294967295
LONG_MIN:   -2147483648
LONG_MAX:   +2147483647
ULONG_MAX:  4294967295
LLONG_MIN:  -9223372036854775808
LLONG_MAX:  +9223372036854775807
ULLONG_MAX: 18446744073709551615

Why is there no + sign printed for U..._MAX? How can I do that?

Dormouse answered 24/9, 2021 at 11:23 Comment(5)
Why do you need it? What problem is that supposed to solve? And considering that unsigned values can't be negative, does it really make sense?Cracknel
printf("ULLONG_MAX: +%llu\n", ULLONG_MAX);? The number is always positive so you can just unconditionally print + if that is really what you want.Fatso
I don't think that the u format specifiers allow you to print the sign (e.g. here, while for d and i the representation ` [-]dddd` is shown, for u it's only ` dddd`).Sophey
It is in the name. Given that “unsigned” literally means without a sign, it is not surprising that numbers without a sign are printed without a sign.Elke
Can you try to compile with compiler warnings enabled and post the result? My compiler produces warnings: warning: '+' flag used with ‘%u’ gnu_printf format [-Wformat=]Rudich
L
2

Why there is no + sign printed for U..._MAX? How can I do that?

If it is unsigned you format it like this, moving the plus sign in front of the format specifier:

printf("...: +%...\n", ...);

If it is signed you format it like you currently do:

printf("...: %+...\n", ...);

I'd guess the reason printf doesn't sign it, is because it's unsigned. Many of the format specifiers are platform or library dependent, so you may encounter a library that adds the plus sign for an unsigned, when it sees %+.

Lamee answered 24/9, 2021 at 11:28 Comment(0)
E
3

This feature is rather poorly documented by the standard, we can only read this (7.21.6.1):

+ The result of a signed conversion always begins with a plus or minus sign. (It begins with a sign only when a negative value is converted if this flag is not specified.)

My take is that this should be read as in + must always be followed by a signed number conversion specifier, such as %d or %f. You used an unsigned specifier %u so my take is that your code has undefined behavior since it mixes + with %u.

Erratic answered 24/9, 2021 at 11:35 Comment(6)
This is further supported by e.g. warnings or errors that the compiler may produce: warning: '+' flag used with ‘%u’ gnu_printf format [-Wformat=]Rudich
I'd argue that it's not really undefined behavior, but rather unspecified behavior.Cracknel
@Someprogrammerdude How come? The C standard doesn't mention what will happen if you use an unsigned specifier. If it was unspecified behavior it would say so explicitly, along the lines of "The result of using conversion specifiers that don't correspond to to signed types is unspecified".Erratic
Maybe I mix the terms... In my mind something that isn't in a specification must be unspecified.Cracknel
@Someprogrammerdude 4/2 says "Undefined behavior is otherwise indicated in this International Standard by the words ‘‘undefined behavior’’ or by the omission of any explicit definition of behavior." So if the standard doesn't mention something, it is UB per default.Erratic
@Erratic Thanks for clearing it up for me. Now comes the hard part: Remembering it... :)Cracknel
L
2

Why there is no + sign printed for U..._MAX? How can I do that?

If it is unsigned you format it like this, moving the plus sign in front of the format specifier:

printf("...: +%...\n", ...);

If it is signed you format it like you currently do:

printf("...: %+...\n", ...);

I'd guess the reason printf doesn't sign it, is because it's unsigned. Many of the format specifiers are platform or library dependent, so you may encounter a library that adds the plus sign for an unsigned, when it sees %+.

Lamee answered 24/9, 2021 at 11:28 Comment(0)
C
1

The conversion specifier u is not a signed conversion specifier while the flag + is used with signed conversion specifiers.

From the C Standard (7.21.6.1 The fprintf function)

  • The result of a signed conversion always begins with a plus or minus sign. (It begins with a sign only when a negative value is converted if this flag is not specified.)

So you have gotten an expected result. The flag + with an unsigned conversion specifier has no effect.

The title of your question would sound more correctly if the words unsigned values were substituted for the words unsigned conversion specifiers. That is there is no great sense to prefix the sign + or - to values that are always outputted as non-negative. When there are outputted signed values then it makes sense to output them with an explicit sign to make the output more readable to distinguish positive and negative values for example when they are outputted in a table

Constance answered 24/9, 2021 at 11:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.