printf() no format string printing character and integer arrays --> garbage

∥☆過路亽.° 提交于 2021-02-05 12:35:20

问题


I'm wondering why printf() when provided an array and no formatting options, successfully prints character arrays but while using integer arrays the compiler throws a warning and a garbage value is printed.

Here's my code:

#include <stdio.h>

int main()
{
   char cr[3] = { 'a', 'b' };
   int ar[3] = { 1, 2 };

   printf("character array output using printf() : ");
   printf(cr);

   printf("\n\nInteger array output using printf() : ");
   printf(ar);
   printf("\n");

   return 0;
}

and here's my output:

../main.c: In function ‘main’:
../main.c:12:4: warning: passing argument 1 of ‘printf’ from incompatible pointer type [enabled by default]
    printf(ar);
    ^
In file included from ../main.c:1:0:
/usr/include/stdio.h:362:12: note: expected ‘const char * restrict’ but argument is of type ‘int *’
 extern int printf (const char *__restrict __format, ...);
            ^
Finished building: ../main.c

回答1:


To answer what exactly happens I want firstly show what your array initializations do. Your array initializer lists are incomplete, there are missing elements as the size is greater than the list. That will result in zero initialization for the missing elements.

1. char cr[3] array:

char cr[3] = { 'a', 'b' };

will lead to:

     character represantation      ==       decimal representation
-+----+----+----+----+----+----+-      -+----+----+----+----+----+----+-
 |    | a  | b  | \0 |    |    |        |    | 97 | 98 | 0  |    |    | 
-+----+----+----+----+----+----+-      -+----+----+----+----+----+----+-
       ^~~~                                   ^~~~
       | char                                 | char
       cr                                     cr

The printf() function is defined as: int printf( const char* format, ... );. That means it takes a char pointer and doesn't change the elements that are pointed to.

If you now pass the cr array to the printf() function the array name will decay to a pointer. The printf() function interprets the format parameter as null terminated character array which is called a C-string. Your cr array is a null terminated C-string as it consists of { 'a', 'b', '\0' }. That means the printf() function can successfully print the string "ab" to stdout.

2. int ar[3] array:

int ar[3] = { 1, 2 };

will lead to:

-+----+----+----+----+----+----+-
 |    | 1  | 2  | 0  |    |    | 
-+----+----+----+----+----+----+-
       ^~~~
       | int
       ar

For now you see no great difference (just type and content) in contrast to the 1st case. But now you're passing the ar array to the printf() function. The array name will decay to an int* and is implicitly casted to const char* (this will bring you the compiler warning you've got). If the printf() function now dereferences the memory it looks like the following (assuming that an int consists of 4 bytes and your machine uses little endian memory representation):

-+----+----+----+----+----+----+----+----+----+----+----+----+----+-
 |    | 1  | 0  | 0  | 0  | 2  | 0  | 0  | 0  | 0  | 0  | 0  | 0  | 
-+----+----+----+----+----+----+----+----+----+----+----+----+----+-
       ^~~~~~~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~
       |                int                 int                  int
       ^~~~ ^~~~ ^~~~ ^~~~ ^~~~ ^~~~ ^~~~ ^~~~ ^~~~ ^~~~ ^~~~ ^~~~
       | char char char char char char char char char char char char
       ar

Instead of getting a string like "12" printed it will consume the both left characters that are the decimal value 1 and 0 (null terminator), see diagram above. The remaining decimal values after 1 and 0 are not recognized as they are after the null terminator. Assuming your machine uses the ASCII table the decimal 1 is not a printable character leading to a garbage value printed.


Proof of concept:

To prove what I write before you can use the following function which takes the same 1st argument as printf(), namely const char*:

void printhexchars(const char* str)
{
   while(*str)
   {
      printf("%03d ", *(str++));
   }
   /* print last character after while loop: '\0' */
   printf("%03d ", *str);
}

This functions prints the integer representation of a null terminated C-string. See example with your arrays char cr[3] and int ar[3] on ideone.com. Of course passing the integer array to the function above will generate the same compiler warning as you already get before.

Output:

character array output using printf() : 097 098 000 

Integer array output using printf() : 001 000

As you can see you get 097 098 000 which is "ab" for your character array.
Your integer array leads to 001 000 which leads to the non printable character with a decimal value of 1.




回答2:


The C language standard declares printf as follows:

int printf(const char *format, ...);

It returns an integer and takes a first parameter of a pointer to a constant character and an arbitrary number of subsequent parameters of arbitrary type.




回答3:


Because the both array as display as character and the chars are keep as ascii code and integers are kept as integer (thanks cpt. obvious). Printf interprets the input as code ascii so in case of integers you have control character which are not very understandable.



来源:https://stackoverflow.com/questions/46110952/printf-no-format-string-printing-character-and-integer-arrays-garbage

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!