-4

If i try to print 1000 as given in C:

printf("%c\n",1000);
printf("%s\n",1000);

What will be the output?Or Will I get error for both lines ?

user10056563
  • 105
  • 4

3 Answers3

4
printf("%c\n",1000);

%c requires an argument of type int (so far, so good) and prints it as a character. 1000 is (almost certainly) outside the range of char or unsigned char, but

If no l length modifier is present, the int argument is converted to an unsigned char, and the resulting character is written.

Conversion to an unsigned integer type is well defined; it's reduced modulo UCHAR_MAX+1. Assuming UCHAR_MAX==255 (which it almost certainly is) the result of the conversion is (unsigned char)232, so it will (attempt to) print character 232. The result is likely to depend on the locale. You're likely to run into problems with 232 (0xe8) being an invalid UTF-8 encoding.

printf("%s\n",1000);

%s requires an argument of type char*. so the behavior is undefined. (What's likely to happen in practice is that the value 1000 is treated as if it were a pointer. It's unlikely that that's a valid address, or that there's a valid string starting at that address.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
2

Using the wrong format specifier for printf invokes undefined behavior bugs, meaning that anything can happen. Pondering about why you get a certain kind of undefined behavior won't give you much in the way of meaningful knowledge, but anyway...

In the case printf("%s\n",1000); you simply lie to the compiler and tell it that 1000 is a pointer to an allocated string of characters. It's hard to tell exactly what will happen - maybe the compiler will run off to address 1000 and attempt to access it, possibly resulting in a crash.

In the case of printf("%c\n",1000); this is actually somewhat deterministic behavior, by accident. All arguments to variadic functions like printf get implicitly promoted. Had you passed a char, it would have been promoted to int and then converted back to char.

But you pass the integer constant 1000 which is of type int. As it happens, printf expects an int after the implicit promotion and it will try to convert 1000 "back" to a char. This means that the compiler will grab the least significant byte of the int and treat that as char (or to be picky, as unsigned char).

1000 == 0x000003E8. The char conversion will grab the least significant E8 byte. And then print whatever that character represents in the symbol table, if anything.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • I don't think the behaviour is undefined. It does exactly what you say, it tries to access the address 1000. I think this is well defined – RoQuOTriX Sep 26 '19 at 09:36
  • @RoQuOTriX in the case of `printf("%s\n",1000);` if pointers are 64-bit and `int` is 32-bit, only 4 bytes will be pushed onto the stack. The `printf` function however expects to find an 8 byte pointer, and the content of the other 4 bytes is unknown. – Weather Vane Sep 26 '19 at 09:40
  • @RoQuOTriX The behaviour is undefined if the wrong format specifier is used. See https://stackoverflow.com/questions/16864552/what-happens-when-i-use-the-wrong-format-specifier – John Sep 26 '19 at 09:43
  • @EricPostpischil Fixed. I hadn't checked what printf says about `%c` in detail, and it does say that there is an implicit conversion from `int` to `unsigned char`. In which case endianess does indeed not matter. – Lundin Sep 26 '19 at 10:43
0

Please refer to the printf format specifiers: http://www.cplusplus.com/reference/cstdio/printf/

%c - used to print a character (char), which normally has a value between -128 to 127 (it can also be 0 to 255)

%s - used to print an array of chars with the last char as NULL (\0)

So printf("%c\n",1000); exhibits implementation defined behaviour as 1000 is greater than 128 (or 255).

and printf("%s\n",1000); is trying to print an array of chars located at address 1000 (which is most likely wrong). It is also undefined behaviour, so anything could happen.

If you are trying to print an integer you should use %d, like such:

printf("%d\n",1000);
John
  • 1,012
  • 14
  • 22
  • `printf("%c\n",1000);` doesn't have undefined behavior. The `int` argument is converted to `unsigned char`. See my answer. – Keith Thompson Sep 26 '19 at 09:14
  • @KeithThompson Agree. I should better say it is implementation defined. – John Sep 26 '19 at 09:15
  • Also, `char` doesn't necessarily have the range 0-255. On desktop systems, -128 to 127 is most common. – Lundin Sep 26 '19 at 09:16
  • @Lundin Yes indeed. That's why I said 'normally'. I fixed the answer accordingly. – John Sep 26 '19 at 09:16
  • @Lundin: The signedness of plain `char` is irrelevant in this case. The standard specifically says the `int` argument is converted to `unsigned char`, which has a range of 0..255 *unless* you're on some exotic system (most likely a DSP) with `CHAR_BIT > 8`. Also, out-of-range integer conversion to an unsigned type is well defined, unlike out-of-range integer conversion to a signed type. – Keith Thompson Sep 26 '19 at 23:50
  • @KeithThompson It is not irrelevant if the passed character is negative, then sign extended during promotion to `int`. What value that will get printed depends on the signedness format of `char`, regardless of the conversion to `unsigned char` later on. – Lundin Sep 27 '19 at 06:36
  • @Lundin It's irrelevant to the code in the question, which passes the `int` value 1000. Do you have an example where it does matter? – Keith Thompson Sep 27 '19 at 09:19
  • @Lundin If you have a signed char and promote it to an int, surely you'll have sign extension. In this case printf demotes the int (1000) to an unsigned char, which involves no sign extension. So the signedness is irrelevant as KeithThompson says, or am I missing something? See section 7.19.6.1 point 8 of C99. – John Sep 27 '19 at 09:51