2

Well, function prototype arguments do implicit conversions, I was wondering if in this example, there is also implicit conversion or not? And if there is no conversion why does it happen? Since what other function prototypes do this conversion?

#include <stdio.h>

int main(void)
{ 
    unsigned char a;
    scanf("%d", &a); // conversion implicit or not ?
    printf("a = %d\n", a); // conversion implicit or not ?
    return 0;
}
  • The **default argument promotions**, as happen for `...` of `printf`, `scanf` are: `char`, `short` rank integers are promoted to `int` or `unsigned int`; `float` to `double`. Since `&a` is of type `unsigned char *`, and **none** of mentioned types, **nothing** is done. You `scanf` *to* unsigned char with `%hhu`; C99+. C89, you need to write a wrapper. – Antti Haapala -- Слава Україні Jan 23 '21 at 14:51

2 Answers2

1
  1. The scanf will write outside the space occupied by the variable - UB. There is no conversion here.

  2. unsigned char value is being promoted to int and passed to the print. But it is not because of the format.

0___________
  • 60,014
  • 4
  • 34
  • 74
1

The variable arguments to scanf and printf will only undergo the default argument promotions. This means that arguments of type float are promoted to type double and integer types smaller than int will be promoted to int. Note that this does not apply to pointers.

In the case of scanf, the %d format specifier is expecting an int * but you're passing in an unsigned char *. These types are not compatible so you have undefined behavior.

In the case of printf, %d expects an int. The unsigned char you're passing in gets promoted to int so in this case it is valid.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Thank you very much, now to understand –  Jan 23 '21 at 14:35
  • Promotions for upcoming types, is it allowed? For example scanf ("% hhu", & a); or scanf ("% hhd", & a); in this case can the types be said to be the same unsigned char and signed char? –  Jan 23 '21 at 14:40
  • @Yuri007 Using `%hhu` would be valid as the argument would match, but not `%hhd`. – dbush Jan 23 '21 at 14:47
  • But now I have another question, for example long x = 15; printf ("% lld", x); // Would this be ub? Why wouldn't long be promoted to long long in this case? If not, why doesn't it happen in this case, only for the char type for int? –  Jan 23 '21 at 14:50
  • @Yuri007 That's the way the rules are written. Only types smaller than `int` are promoted. The compiler isn't required to look at the format string to "figure out" what it expects. – dbush Jan 23 '21 at 14:52
  • So, in this case, the example I gave now is different from this void f (long long x); long y; f (y); In this case, as I declared a variable as long long, the variable y will be promoted to long long, now when I use a format string the compiler does not check the type to do the automatic conversion, correct? –  Jan 23 '21 at 14:56
  • @dbush but many compilers are nice and look into the format string issuing warnings if they do not like something – 0___________ Jan 23 '21 at 15:10
  • @Yuri007 In that case it is fine because the destination type is known by the compiler so a *conversion* (not a promotion) is done. What happens with `printf` and `scanf` applies to *any* function that uses variable arguments (i.e. `...` in the argument list). – dbush Jan 23 '21 at 15:15
  • And what is the difference in conversion to promotion? –  Jan 23 '21 at 15:16