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?

user438383
  • 5,716
  • 8
  • 28
  • 43
Jin Kwon
  • 20,295
  • 14
  • 115
  • 184
  • 2
    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? – Some programmer dude Sep 24 '21 at 11:26
  • 3
    `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. – kaylum Sep 24 '21 at 11:26
  • 2
    I don't think that the `u` format specifiers allow you to print the sign (e.g. [here](https://en.cppreference.com/w/c/io/fprintf), while for `d` and `i` the representation ` [-]dddd` is shown, for `u` it's only ` dddd`). – Bob__ Sep 24 '21 at 11:27
  • 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. – Eric Postpischil Sep 24 '21 at 11:43
  • 1
    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=]` – Cheatah Sep 24 '21 at 11:44

3 Answers3

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.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 2
    This is further supported by e.g. warnings or errors that the compiler may produce: `warning: '+' flag used with ‘%u’ gnu_printf format [-Wformat=]` – Cheatah Sep 24 '21 at 11:42
  • I'd argue that it's not really undefined behavior, but rather unspecified behavior. – Some programmer dude Sep 24 '21 at 12:58
  • @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". – Lundin Sep 24 '21 at 13:25
  • Maybe I mix the terms... In my mind something that isn't in a *specification* must be un*specified*. – Some programmer dude Sep 24 '21 at 14:07
  • 2
    @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. – Lundin Sep 24 '21 at 14:32
  • @Lundin Thanks for clearing it up for me. Now comes the hard part: Remembering it... :) – Some programmer dude Sep 24 '21 at 14:49
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 %+.

GoWiser
  • 857
  • 6
  • 20
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

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335