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

标签 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

最佳答案

为了回答到底发生了什么,我想首先展示你的数组初始化的作用。您的数组初始值设定项列表不完整,由于大小大于列表而缺少元素。这将导致 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 数组是一个以 null 结尾的 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);
}

此函数打印以 null 结尾的 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 的不可打印字符。

关于c - printf() 无格式字符串打印字符和整数数组 --> 垃圾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46110952/

相关文章:

c - char str[] 中大括号之间的值是什么意思?

c - 在 C 中写入 char* 数组会引发段错误

c - printf() 中的格式化程序大小

c - 从二维字符数组打印字符串

c - 知道最大字符数的行 (C)

c - Nucleo STM32F7 上的 UDP 回显

c - 从不可变字符串返回 const char**

c - 哪里可以找到 `stdin`宏声明?

C从文件中获取字符串数据,输出一些意想不到的结果

c - 我是否必须从每个初始化的字符串中释放内存?