printf() 无格式字符串打印字符和整数数组 -->垃圾 [英] printf() no format string printing character and integer arrays --> garbage

查看:67
本文介绍了printf() 无格式字符串打印字符和整数数组 -->垃圾的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

这是我的代码:

#include int main(){字符 cr[3] = { 'a', 'b' };int ar[3] = { 1, 2 };printf("使用printf()输出字符数组:");printf(cr);printf("\n\n使用 printf() 输出整数数组:");printf(ar);printf("\n");返回0;}

这是我的输出:

../main.c: 在函数‘main’中:../main.c:12:4: 警告:从不兼容的指针类型传递printf"的参数 1 [默认启用]printf(ar);^在 ../main.c:1:0 包含的文件中:/usr/include/stdio.h:362:12:注意:预期为‘const char *restrict’,但参数的类型为‘int *’extern int printf (const char *__restrict __format, ...);^完成的建筑:../main.c

解决方案

要回答到底发生了什么,我想首先展示您的数组初始化的作用.您的数组初始值设定项列表不完整,由于大小大于列表,因此缺少元素.这将导致缺失元素的零初始化.

1.char cr[3] 数组:

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

将导致:

 字符表示 == 十进制表示-+----+----+----+----+----+----+- -+----+----+----+----+----+----+-|||乙 |\0 |||||97 |98 |0 |||-+----+----+----+----+----+----+- -+----+----+----+----+----+----+-^~~~ ^~~~|字符 |字符CR CR

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

如果您现在将 cr 数组传递给 printf() 函数 数组名将衰减为一个指针.printf() 函数将 format 参数解释为 null 终止的字符数组,称为 C 字符串.您的 cr 数组是一个以空字符结尾的 C 字符串,因为它由 { 'a', 'b', '\0' } 组成.这意味着 printf() 函数可以成功地将字符串 "ab" 打印到 stdout.

2.int ar[3] 数组:

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

将导致:

-+----+----+----+----+----+----+----+-||1 |2 |0 |||-+----+----+----+----+----+----+----+-^~~~|整数ar

目前,与第一种情况相比,您没有发现太大的区别(只是类型和内容).但是现在您将 ar 数组传递给 printf() 函数.数组名称将衰减为 int* 并隐式转换为 const char*(这将为您带来编译器警告).如果 printf() 函数现在取消引用内存,它看起来如下所示(假设 int 由 4 个字节组成,并且您的机器使用 小端内存表示):

-+----+----+----+----+----+----+----+----+----+----+----+----+----+----+-||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 charar

打印出来的不是像 "12" 这样的字符串,它会消耗左边的两个字符,即十进制值 1 和 0(空终止符),见上图.1 和 0 之后的其余十进制值被识别,因为它们在空终止符之后.假设您的机器使用 ASCII 表,十进制 1 不是可打印字符,导致打印垃圾值.

<小时>

概念证明:

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

void printhexchars(const char* str){而(* str){printf("%03d", *(str++));}/* 打印 while 循环后的最后一个字符:'\0' */printf("%03d", *str);}

此函数打印空终止 C 字符串的整数表示.请参阅示例,使用您的数组char cr[3]int ar[3] 在 ideone.com 上.当然,将整数数组传递给上面的函数会产生与之前相同的编译器警告.

输出:

<块引用>

使用 printf() 输出字符数组:097 098 000使用 printf() 的整数数组输出:001 000

如您所见,您将获得 097 098 000,它是您的字符数组的 "ab".
您的整数数组导致 001 000 导致十进制值为 1 的不可打印字符.

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

解决方案

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.

这篇关于printf() 无格式字符串打印字符和整数数组 -->垃圾的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆