-6

This code will print:

s = 1, i = 65537, f = 65537.000000, c = 1

I need help in understanding why is it printing c=1.

The code:

#include <stdio.h>  // Standard input-output library
#include <stdlib.h> // Standard general utilities library

int main(void) {
   int i = 65537;
   unsigned short s = (unsigned short)i;
   float f = (float)i;
   char c = (char)i;
   printf("s = %u, i = %d, f = %f, c = %d\n", s,i,f,c);
   system("PAUSE");
   return (0);
}
Yuval
  • 180
  • 13
  • Because you used the wrong specifier. You print `char`s with `%c`, not `%d`. – StoryTeller - Unslander Monica Nov 16 '16 at 19:33
  • 2
    @StoryTeller Not if you want to see the numeric value. – aschepler Nov 16 '16 at 19:35
  • 2
    c=1 for the same reason s=1 – Stefan Nov 16 '16 at 19:36
  • 2
    (On your machine) Char is 8 bits. Int is 32 bits. The difference is that 65537 fully fits in int but not char. You get 1 because 65537 % (2^8) = 1. – Lupe Nov 16 '16 at 19:36
  • The conversion from int to char is implementation defined. Apparently your implementation converts 65537(int) to 1(char). http://port70.net/~nsz/c/c11/n1570.html#6.3.1.3p3 – pmg Nov 16 '16 at 19:36
  • 1
    What size (in bytes) is `char`? What size (in bytes) is `int`? What are the max values of each of those types? What happens when a number overflows? – Ken White Nov 16 '16 at 19:37
  • @aschepler, and we know the OP *meant* to do it how? – StoryTeller - Unslander Monica Nov 16 '16 at 19:38
  • @StoryTeller - It doesn't matter if he meant it. The question asks "why does the code output , not "why doesn't the code output the thing that you might think I meant to have it output instead". – BadZen Nov 16 '16 at 19:40
  • Shouldn't one use %hhd to output numeric value of a char instead of just %d? – Franko Leon Tokalić Nov 16 '16 at 19:41
  • @BadZen, "You used the wrong specifier" is just as valid a response to ""why does the code output ". – StoryTeller - Unslander Monica Nov 16 '16 at 19:41
  • 1
    Hint: the [binary representation](https://en.wikipedia.org/wiki/Binary_number#Counting_in_binary) of 65537 is 10000000000000001. – user3386109 Nov 16 '16 at 19:42
  • 1
    @StoryTeller, This looks like a homework problem. It's not unreasonable to assume he means to print out the numeric value because all of the other things he prints out are numbers. – Lupe Nov 16 '16 at 19:42
  • Also, int to char truncation *is* well-defined. See http://stackoverflow.com/questions/5881895/truncating-an-int-to-char-is-it-defined. We also know `sizeof(char) == 1`, so this isn't platform-specific. – BadZen Nov 16 '16 at 19:42
  • StoryTeller thanks for the help , but I got this assignment from my teacher , im supposed to write down what the given code is printing and explain why , @BadZen thanks for being extremly helpful . but can you be more specific as im only 1 hour deep into C , I mean like verbly explaining this in what approach would you go? – Yuval Nov 16 '16 at 20:03
  • @Byteventurer: That's somewhat true. Problem is `char` has implementation-defined signed-ness, so it is not clear if it should be `%hhu`. But nevertheless, `%d` is correct, too due to integer promotion. – too honest for this site Nov 16 '16 at 20:08
  • 2
    @BadZen: if `char` is signed, it is implementation defined, it only is "well defined" if we know what the implementation is and how it handles this. The linked question is about `unsigned char`! – too honest for this site Nov 16 '16 at 20:10
  • @Olaf: Yeah, knew about the signed-ness, I was just using "d" because it is used here. I didn't know not writing "hh" is valid, though, thanks. What is the point of using "hh" then, if it is being promoted? – Franko Leon Tokalić Nov 16 '16 at 20:22
  • Ook. @Olaf is correct. I forgot `char` could be signed, is the issue. Been doing too much Go. :) There's actually a famous crypto bug (in a Blowfish implementation) about this, so should have remembered! – BadZen Nov 16 '16 at 20:27
  • Possible duplicate of [convert int to short in C](http://stackoverflow.com/questions/18276225/convert-int-to-short-in-c) – Baum mit Augen Nov 16 '16 at 21:41
  • @Byteventurer: 1) Never use `char` if you intend to do arithmetics. Use `unsigned char` or `signed char` explicitly. It is good practice to use the plain `char` only for characters where it does not matter much (and the libraries expect `char`). For fixed width (e.g. 8 bit integers), you should never use the standard integer types, but the fixed width types from `stdint.h`. 2) Good point, I don't use these functions in my projects, so I never thought if it makes any difference. ... – too honest for this site Nov 16 '16 at 21:42
  • In general, one should use the correct conversion type specifier, even if it does not matter much (sorry, but that's the best I can come up with here). It makes more difference for the `scanf` family. It does matter for `unsigned short` and 16 bit `int`. – too honest for this site Nov 16 '16 at 21:43
  • @Olaf I guess it makes a difference for scanf only then, thanks. I do understand the signed-ness of char, as I said, I was just confused about the format specifier. – Franko Leon Tokalić Nov 16 '16 at 21:53
  • @Byteventurer: I'd be careful about such assumptions. There might be combinations of numbers of bits/byte, number of bits for the standard types, encoding, etc. which indeed make a difference. Just because I cannot instantly state one, does not mean there is none. – too honest for this site Nov 16 '16 at 22:06
  • @Olaf Oh, I see, okay. – Franko Leon Tokalić Nov 16 '16 at 22:11
  • Hi all its the OP , I didnt write this code , I was only instructed by the teacher to analyse it , – Yuval Nov 19 '16 at 15:55

1 Answers1

2

If to output the variable i in hex representation like this

#include <stdio.h>

int main(void) 
{
    int i = 65537;

    printf( "%#0x\n", i );

    return 0;
}

then you will see that it looks like

0x10001

Type char always occupies one byte. Thus in this assignment

char c = (char)i;

one byte of the object i

0x10001
     ^^

is stored in the variable c.

In the printf statement in your program

printf("s = %u, i = %d, f = %f, c = %d\n", s,i,f,c);
                                ^^^^^^

it is outputted using type specifier %d. So its internal value is outputted as an integer of type int.

Usually objects of the type unsigned short occupy two bytes. Thus in this assignment

unsigned short s = (unsigned short)i;

the value in the first two bytes of object i

0x10001
   ^^^^

will be assigned to variable s.

So c and s the both will have value 1.

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