在getchar()和printf()中真正发生了什么?解释整个过程

时间:2017-06-06 13:32:48

标签: c function return-value implementation conceptual

我正在学习 geeksforgeeks ,当我看到这个时,我想到了一个想法,因为getchar()和其他类似的函数返回一个int(无论是由于失败程序或EOF)然后为什么格式说明符是%c,为什么不%d(or %i)

// Example for getchar() in C
#include <stdio.h>
int main()
{
   printf("%c", getchar());
   return 0;
}

我知道我们输入的字符是一个字符,它由函数getchar()拍摄,我们使用%c显示它。

但我的问题是整个过程中getchar()printf()内部实际发生的问题,其中getchar()返回整数,存储它的位置以及我们输入的字符是如何存储的printf() printf()内发生的printf()显示了什么?

我对C standard library实现做了一些研究,并了解printf是libc(又名_update_by_query)的一部分,是一个可变函数(printf)但是我没有知道这个函数里面真正发生了什么,以及它如何通过格式说明符知道它必须打印字符或int?

请帮助我学习正在进行的整个过程。

3 个答案:

答案 0 :(得分:2)

getchar的手册页说明如下:

  

fgetc()从流中读取下一个字符并将其作为一个返回   unsigned char投放到int或文件结尾或错误的EOF。

     

getc()相当于fgetc(),但它可以实现为   不止一次评估流的宏。

     

getchar()相当于getc(stdin)

因此,假设您输入了字符A。假设您的系统使用字符的ASCII表示,则此字符的ASCII值为65.因此,在这种情况下,getchar将返回65作为int

int返回的getchar值为65,然后作为第二个参数传递给printfprintf函数首先查看格式字符串并查看%c格式说明符。 printf的手册页对%c

说了以下内容
  

如果不存在l修饰符,则int参数将转换为                 unsigned char,并写出结果字符。

所以printf将下一个参数读作int。由于我们传入了值{65的int,因此它就是它所读取的内容。然后将该值转换为unsigned char。由于它仍处于该类型的范围内,因此值仍为65. printf然后打印该值的字符。由于65是字符A的ASCII值,因此出现字符A

答案 1 :(得分:1)

(我假设您的计算机有x86-64处理器并运行Linux)

  

为什么使用的格式说明符是%c,为什么不是%d(或%i)。

想象一下,相应的参数(printf)是99(int)。如果您使用%c,则会显示字母c(ASCII代码99)。如果您使用%d%i,那么99会显示printf,等等......

正如您所注意到的,

printf是一个可变函数。它是使用variadic primitives实现的,如va_startva_end,它们是扩展到编译器已知的内置函数的宏。在一个名为ABI(calling convention)的文档中,如何传递确切的参数并给出结果(application binary interface)(在某些处理器和操作系统特定的方式中)。

在某些C标准库实现中,printf(以及相关函数,如vfprintf)最终会使用putc或其他相关内容。

请注意,标准I / O函数(<stdio.h>中的函数)可能在某些operating system的帮助下提供。有关操作系统的更多信息,请阅读Operating Systems : Three Easy Pieces

通常,C standard library会使用某些system calls与操作系统kernel进行交互。对于Linux,这些列在syscalls(2)中,但请阅读Advanced Linux Programming。要输出一些数据,将使用write(2)系统调用(但C标准库通常是缓冲,请参阅setvbuf(3))。

BTW,对于Linux / x86-64,GNU glibc&amp; musl-libcfree softwareC standard library实现,您可以研究它们的源代码(大部分内容都是用C语言编写的,只需要一点点系统调用粘合剂)。 / p>

  

但我的问题是在整个过程中getchar()和printf()内部实际发生了什么,其中getchar()返回整数,它存储在哪里......?

ABI定义int返回函数的结果通过寄存器%raxgetchar(与其他int返回函数一样)以这种方式工作。请参阅X86-64 Linux ABI引用的here

  

...以及我们输入的字符是如何通过printf()显示的,即printf()内部发生了什么?

在许多软件层之后,当stdout流被刷新时(例如通过调用fflush(3)\n换行符或exit(3)时间,包括从main返回crt0代码),C标准库将使用write(2)系统调用。内核将处理它以显示某些内容(但细节非常复杂,请先阅读tty demystified)。实际上涉及数百万个源代码行(包括内核内部 - 在DRM内部阅读display server,例如X.OrgWayland - GPU内的一些代码3}} - ,在terminal emulator内。 Linux是免费软件,因此原则上你可以研究所有这些(但这需要超过一生,典型的Linux发行版有大约二十亿行源代码)。另请参阅OSDev wiki,其中提供了一些实用信息,包括native Intel grapĥics(这是当今最原始的图形)。

PS。您需要花费十多年的时间来了解所有细节(我不这么做)。

答案 2 :(得分:1)

要了解您必须阅读default argument promotions

  

其中getchar()返回那个存储的整数

C为您处理此事。

  

我们输入的字符是如何通过// split by pipe string[] strArray = text.Split('|'); // taking sixth element in resulting array string value = strArray[5].ToString();

显示的

printf()告诉%c打印一个角色。