How the value of an int being printed as a char? - c

In below program ,How is int being converted into char by printf()? Is it being demoted implicitly?
#include<stdio.h>
int main()
{
int c=2;
printf("%c",c);
}

The code is working fine! You will just get the ASCII character for c.
Let´s look on another example:
int c;
for (c = 97; c < 123; c++)
{
printf("%c",c);
}
This code would generate the following output:
abcdefghijklmnopqrstuvwxyz
If the value of c is greater than the biggest value of char the output just starts from the begin. This means c = 1 would generate the same output as c = 257.

In your code,
printf("%c",c);
works, because, as per the C11 standard, chapter §7.21.6.1, The fprintf() function, the %c format specifier,
c
If no l length modifier is present, the int argument is converted to an
unsigned char, and the resulting character is written.
So, the value held by c will get converted to an unsigned char, which then will be printed out using %c format specifier.

Related

Why does printf give me the following output?

I'm working through The C Programming Language book and understand that if I had a line of code like:
int c;
printf("%d", c = 5);
I will get an output of 5, because (c = 5) has the value of the RHS value of the assignment.
In a similar way:
int c;
printf("%d", c = getchar(c));
will give me the integer value of the first char in the stdin buffer, because (c = getchar()) has the value of the RHS which is just the getchar() function.
I was playing around with it and used the following using VS Code:
#include <stdio.h>
int main()
{
int c, b;
printf("%d\t%d", c = (b = 7));
}
The output I get is:
7
6422376.
and not
7
7
Why is this? The second output is the same value (6422376) no matter whatever value I use for b, eg (b = 3).
The expression c = (b = 7) is a single expression, and as such a single argument passed to the printf function.
The second %d format specifier leads to undefined behavior as there is no second argument matching it.
because for second %d there is no matching argument as c=(b=7) is a single expression
Your code is not well-formed : you have only one parameter for printf when you should have two.
#include <stdio.h>
int main()
{
int c, b;
printf("%d\t%d", c = (b = 7),b);
}
you can try these code to print the value of b. There is only one parameter in your printf function, and 2 format specifier, so compiler assumes any garbage value for another %d.

+'0' wont give char value of int

I was trying to make this int to char program. The +'0' in the do while loop wont convert the int value to ascii, whereas, +'0' in main is converting. I have tried many statements, but it won't work in convert() .
#include<stdio.h>
#include<string.h>
void convert(int input,char s[]);
void reverse(char s[]);
int main()
{
int input;
char string[5];
//prcharf("enter int\n");
printf("enter int\n");
scanf("%d",&input);
convert(input,string);
printf("Converted Input is : %s\n",string);
int i=54;
printf("%c\n",(i+'0')); //This give ascii char value of int
printf("out\n");
}
void convert(int input,char s[])
{
int sign,i=0;
char d;
if((sign=input)<0)
input=-input;
do
{
s[i++]='0'+input%10;//but this gives int only
} while((input/=10)>0);
if(sign<0)
s[i++]='-';
s[i]=EOF;
reverse(s);
}
void reverse(char s[])
{
int i,j;
char temp;
for(i=0,j=strlen(s)-1;i<j;i++,j--)
{
temp=s[i];
s[i]=s[j];
s[j]=temp;
}
}
Output screenshot
Code screenshot
The +'0' in the do while loop wont convert the int value to ascii
Your own screenshot shows otherwise (assuming an ASCII-based terminal).
Your code printed 56, so it printed the bytes 0x35 and 0x36, so string[0] and string[1] contain 0x35 and 0x36 respectively, and 0x35 and 0x36 are the ASCII encodings of 5 and 6 respectively.
You can also verify this by printing the elements of string individually.
for (int i=0; string[i]; ++i)
printf("%02X ", string[i]);
printf("\n");
I tried your program and it is working for the most part. I get some goofy output because of this line:
s[i]=EOF;
EOF is a negative integer macro that represents "End Of File." Its actual value is implementation defined. It appears what you actually want is a null terminator:
s[i]='\0';
That will remove any goofy characters in the output.
I would also make that string in main a little bigger. No reason we couldn't use something like
char string[12];
I would use a bare minimum of 12 which will cover you to a 32 bit INT_MAX with sign.
EDIT
It appears (based on all the comments) you may be actually trying to make a program that simply outputs characters using numeric ascii values. What the convert function actually does is converts an integer to a string representation of that integer. For example:
int num = 123; /* Integer input */
char str_num[12] = "123"; /* char array output */
convert is basically a manual implementation of itoa.
If you are trying to simply output characters given ascii codes, this is a much simpler program. First, you should understand that this code here is a mis-interpretation of what convert was trying to do:
int i=54;
printf("%c\n",(i+'0'));
The point of adding '0' previously, was to convert single digit integers to their ascii code version. For reference, use this: asciitable. For example if you wanted to convert the integer 4 to a character '4', you would add 4 to '0' which is ascii code 48 to get 52. 52 being the ascii code for the character '4'. To print out the character that is represented by ascii code, the solution is much more straightforward. As others have stated in the comments, char is a essentially a numeric type already. This will give you the desired behavior:
int i = 102 /* The actual ascii value of 'f' */
printf("%c\n", i);
That will work, but to be safe that should be cast to type char. Whether or not this is redundant may be implementation defined. I do believe that sending incorrect types to printf is undefined behavior whether it works in this case or not. Safe version:
printf("%c\n", (char) i);
So you can write the entire program in main since there is no need for the convert function:
int main()
{
/* Make initialization a habit */
int input = 0;
/* Loop through until we get a value between 0-127 */
do {
printf("enter int\n");
scanf("%d",&input);
} while (input < 0 || input > 127);
printf("Converted Input is : %c\n", (char)input);
}
We don't want anything outside of 0-127. char has a range of 256 bits (AKA a byte!) and spans from -127 to 127. If you wanted literal interpretation of higher characters, you could use unsigned char (0-255). This is undesirable on the linux terminal which is likely expecting UTF-8 characters. Values above 127 will be represent portions of multi-byte characters. If you wanted to support this, you will need a char[] and the code will become a lot more complex.

C programming -storing characters into ints?

#include <stdio.h>
int main (void)
{
int c;
while ( (c = getchar ()) != EOF )
putchar (c);
return 0;
}
So in this program, there is c = getchar (). So i would assume that getchar returns to an integer regardless of what you type?
If that was the case, if I had the code:
#include <stdio.h>
int main (void)
{
char c;
c = getchar();
printf("%c",c);
return 0;
}
It should not work. As if I typed 'y' for example, the getchar function can return to an integer that is 2digits or more and cannot be stored in a char variable. Yet it worked.... In fact, when I type 'f' c becomes f. But why??
Characters are integers, or rather there are contexts where certain integer values are interpreted as characters. The type char is just an integer type in C, so an int can hold all values of a char.
One reason why getchar returns an int is because the special value EOF is not any of the integer values that represent characters (because if it were, you could not distinguish end of file from such a character being input). Once you have checked that the value returned by getchar was not EOF, all other possible return values are characters.
So in this program, there is c = getchar (). So i would assume that getchar returns to an integer regardless of what you type?
True. Detail: int getchar() returns not any integer but an int. The return value is either in the unsigned char range (example 0 ... 255) or EOF. EOF is a negative value.
char c = getchar();
printf("%c",c);
... should not work. As if I typed 'y' for example, the getchar function can return to an integer that is 2 digits or more and cannot be stored in a char variable. Yet it worked.... In fact, when I type 'f' c becomes f. But why??
If the user types y, the typical reuslt is a valueof 121 (ASCII y). The int in not "2 digits or more". The int is a value store in memory, typical 32-bits. It is not store as "digits".
The printf("%c",c); accepts an int as to match the "%c". As a char, c goes though integer promotion (to an int) before being passed to printf(char *format, ...) all it well specified.
The following will typically all print the same. "%c" recieves the int value, converts it to an unsigned char and then print the corresponding character associate with that value. usually ASCCI y.
char c = 'y';
printf("%c", c);
printf("%c", 'y');
printf("%c", 121);
printf("%c", 121 + 256);

What happens when using scanf("%d", &c) while c is a char?

the code is like this:
char c;
scanf("%d", &c);
inputting 3...
My guess is that when 3 is inputted, it is as type int;
and then type-demoted to char and assigned to c;
I print the value of c in specifier %d yielding 3, seems to be as expected;
but printing the value of c with specifier %c yields --a blank-- on the terminal;this is one question...(1);
to test more I furthermore declare a variable ch with type char and initialized it like this:
char ch = 1;
and the test is like this:
(i&j)? printf("yes") : printf("no");
and the result is "no"
I print out the value of i&j, and it is 0
but 1&3 should be 1? this is another question....(2);
my question is (1) and (2)
You're actually invoking undefined behavior doing that.
By using the format string %d, you're telling scanf to expect an int* as a parameter and you're passing it a pointer to a single character. Remember that scanf has no further type information on what you're passing it than what you're putting in the format string.
This will result in scanf attempting to write an int sized value to memory at an address that points to a char sized reservation, potentially (and for most architectures) writing out of bounds.
After invoking UB, all bets are off on your further calculations.
Suppose that scanf() were not a varargs-function, but a plain ordinary function taking a pointer-to-int as the 2nd argument:
int noscanf(char *format, int *ptr)
{
*ptr = 42;
return 1;
}
int main(void)
{
char ch;
int rc;
// This should *at least* give a warning ...
rc = noscanf("Haha!" , &ch);
return 0;
}
Now, scanf() is a varargs function. The only way for scanf() to determine the type of the (pointer) arguments is by inspecting the format string. And a %d means : the next argument is supposed to be a pointer to int. So scanf can happily write sizeof(int) bytes to *ptr.
I can't see a variable jthere. So i&j will be 0. And yes, if i == 1 and j == 3 then i & j == 1.
(i&j)? printf("yes") : printf("no");
statement gives the output yes,for i=1 and j=3.
And for (1) question ASCII 3 is for STX char which is not printable.

C/C++ casting problems, unsigned char to char

i have an unsigned char which i need to convert to char before printf. So the example code goes like this:
unsigned char y = sample.result;
char x = (char)y;
printf("%c \n", x);
However, printf does not print x but if i use cout, x prints correctly.I have no idea why so. How to i convert a unsigned char variable to a char? Am i doing it wrong? reinterpret_casting is only for pointer and mine are not pointers. Thanks in advance.
EDIT: Command prompt returns me a smiley face "☺" for the value of sample.result which corresponds to unsigned char 1. And apparently netbeans is unable to print this smiley face. I have no idea how it got translated into a smiley face. Any help?
EDIT 2: I just realized you can't print char x = 1; in netbeans, and printing it in command prompt yields the smiley face. Reasons? :(
If char x = 1 and you want a 1 to be printed out, you need to use %d instead of %c in your format specifier. %c prints the ASCII representation of the number, which for 1 is an unprintable character called "start of heading."
Try making x an int instead of char and see if that works. C rules required all char parameters to be converted to int, and printf is a C function.
The %c conversion for printf is only for characters in the basic character set. It seems you have an extended character that you want to print, so you'd have to use the appropriate tool for that. The type for that would be wchar_t and the print format %lc. But beware this depends a lot of your execution environment, locale settings and stuff like that.
And BTW in many circumstances narrow types like char are just converted to int or unsigned, so there is no need to cast it, and in fact other than your title suggests your problem has not much to do with casting.
I'm not confident in this answer, but I just wrote a simple test program that compiles and prints the letter A without casting the unsigned char back to a char.
#include <stdio.h>
int main()
{
unsigned char c = 'A';
printf("%c\n",c);
return 0;
}
Casting directly also worked:
#include <stdio.h>
int main()
{
unsigned char c = 'A';
printf("%c\n",(char)c);
return 0;
}
Doing it your way ALSO worked...
#include <stdio.h>
int main()
{
unsigned char c = 'A';
char d = (char)c;
printf("%c\n",d);
return 0;
}
So I assume I'm doing something wrong, now. Or maybe something else is your problem?
Here the equation of conversion
the algorithm for char c to unsigned char uc.
return (c>127) ? (unsigned char)(-(256 + c)) : (unsigned char)c;
the algorithm for unsigned uc to char c.
return (uc < 0) ? (char)(256-(char)abs(uc)) : (char)uc;

Resources