printf()没有格式字符串打印字符和整数数组 - >垃圾

时间:2017-09-08 07:28:05

标签: c pointers printf

我想知道为什么printf()提供数组而没有格式化选项,成功打印字符数组但在使用整数数组时,编译器会抛出警告并打印垃圾值。

这是我的代码:

#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;
}

这是我的输出:

../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

3 个答案:

答案 0 :(得分:3)

C语言标准声明 printf ,如下所示:

>>> s = ''.join(format(x, '02x') for x in ba)
>>> print(s.upper())
6745230F33CC55AA0133CC55AA

它返回一个整数,并获取指向常量字符的指针的第一个参数和任意类型的任意数量的后续参数。

答案 1 :(得分:3)

要回答究竟发生了什么,我首先想要展示你的数组初始化的作用。您的数组初始化列表不完整,缺少元素,因为大小大于列表。这将导致zero initialization for the missing elements

<强> 1。 char cr[3]数组:

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

将导致:

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

printf()函数定义为:int printf( const char* format, ... );。 这意味着它需要char指针,并且不会更改指向的元素。

如果您现在将cr数组传递给printf()函数the array name will decay to a pointerprintf()函数将format参数解释为null terminated character array which is called a C-string。您的cr数组是一个空终止的C字符串,因为它由{ 'a', 'b', '\0' }组成。这意味着printf()函数可以成功地将字符串"ab"打印到stdout。

<强> 2。 int ar[3]数组:

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

将导致:

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

现在你看到与第一种情况相比没有太大的区别(只是类型和内容)。但现在您将ar数组传递给printf()函数。数组名称将衰减为int*并隐式转换为const char*(这将为您带来编译器警告您已获得)。如果printf()函数现在取消引用内存,则它看起来如下(假设int由4个字节组成,而您的机器使用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

不会得到像"12"这样的字符串,而是使用左边的两个字符,即十进制值1和0(空终止符),请参见上图。 1和0之后的剩余十进制值是,因为它们位于空终止符之后。假设您的机器使用the ASCII table,则小数1不是可打印字符,导致打印垃圾值。

概念证明:

要证明我写的内容,你可以使用以下函数,该函数采用与printf()相同的第一个参数,即const char*

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

此函数打印空终止C字符串的整数表示形式。见example with your arrays char cr[3] and int ar[3] on ideone.com。当然,将整数数组传递给上面的函数会产生与之前相同的编译器警告。

<强>输出:

character array output using printf() : 097 098 000 

Integer array output using printf() : 001 000

正如您所看到的,您的角色数组097 098 000"ab" 整数数组导致001 000,导致不可打印的字符,小数值为1。

答案 2 :(得分:0)

因为显示为字符和字符的数组都保持为ascii代码,整数保持为整数(感谢cpt。明显)。 Printf将输入解释为代码ascii,因此在整数的情况下,你有控制字符,这是不可理解的。