5

If i write a very simple line of code in C:

printf("Ascii char for %d is %c\n",65,65);

It simply prints A, as ascii value of 65 corresponds to character A. But if I use the same code in shell and write the command

printf "Ascii char for %d is %c\n" 65 65

it shows the output as Ascii char for 65 is 6. I was expecting the same output as in the C language and logically also it should print the character corresponding to the given ascii code.

Why is it showing different behaviour in these cases?

6

The %c takes a string and prints the first character of that string. If the string is 65, as in your example, then it would print 6.

This is specified by the POSIX specification for the printf utility:

The argument to the c conversion specifier can be a string containing zero or more bytes. If it contains one or more bytes, the first byte shall be written and any additional bytes shall be ignored. If the argument is an empty string, it is unspecified whether nothing is written or a null byte is written.

The argument operands shall be treated as strings if the corresponding conversion specifier is b, c, or s [...]

This means that the argument of the %c format is interpreted different in C (where a small positive integer will be converted to a char) and in the shell (where the same integer remains a string containing several digit characters). The format itself does the same thing though; it outputs a single byte as a character.

However:

$ printf '%d %b\n' 65 '\0101'
65 A

101 is 65 in octal. And %b is specified in POSIX as

An additional conversion specifier character, b, shall be supported as follows. The argument shall be taken to be a string that can contain <backslash>-escape sequences. [...]

\0ddd, where ddd is a zero, one, two, or three-digit octal number that shall be converted to a byte with the numeric value specified by the octal number.

It's an additional conversion specifier, since it's not available in standard C. It is however needed in the shell as we don't have typed variables (in the POSIX shell).

Also:

$ printf '%d %b\n' 65 "$( printf '\\0%o\n' 65 )"
65 A

Here we first convert 65 to an octal number in the \0ddd format using %o, before using the result of that in another printf that uses %b.

  • so it means %c does shows a different behaviour in LINUX as compared to C ?right ? – Noshiii Jan 24 at 21:58
  • 1
    @Noshiii I would say that it behaves slightly differently in C than in the shell, yes. The argument that you pass in the shell is always a string, while in C it's a typed integer. The actual output is similar is nature though: A single character is outputted. It's not the same character because of how the argument is processed. – Kusalananda Jan 24 at 22:01
  • @Noshiii I've added more explanation regarding this to the answer. – Kusalananda Jan 24 at 22:25
  • %c in C takes an int and converts that to unsigned char according to the book HARBISON, Samuel P. C: a reference manual. Prentice Hall, 2002. – thrig Jan 25 at 0:32
  • @thrig I have slightly amended my choice words in the sentence that I think you are referring to. – Kusalananda Jan 25 at 6:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.