如何在C中没有库函数的情况下打印变量的任何字符,字符串或值?

时间:2009-01-22 06:59:58

标签: c printing printf character putchar

例如,如果我不应该使用像printf,putchar这样的标准库函数,那么如何轻松地将字符打印到屏幕上。有没有简单的方法来做到这一点。我不太了解系统调用,如果我必须使用它们,那么如何?

那么任何一个建议都可以在不使用库函数的情况下轻松打印吗?

4 个答案:

答案 0 :(得分:15)

在标准C中,你不能。 C中定义的唯一I / O是通过C标准库函数。

在给定的平台上,可能有办法:

  • 直接拨打内核电话。您可能需要编写一些内联汇编来执行此操作。您可以直接进行litb的write调用,而无需使用C库。抓住C库的源代码,看看它是如何完成的。
  • 直接写入帧缓冲区。多用户操作系统通常不允许这样做(至少不进行任何库/内核调用)。

除非您正在编写自己的C库,否则我不确定您为什么要这样做。

答案 1 :(得分:6)

在linux中,您可以使用write系统调用:

write(1, "hello\n", 6); // write hello\n to stdout

如果你不能得到足够的,你可以更低一点,一般调用系统调用:

syscall(__NR_write, 1, "hello\n", 6);

值得了解strace,您可以使用它来查看任何特定程序在运行时使用的系统调用。但请注意,对于“一些简单的解析器”,几乎不需要使用原始系统调用。更好地使用c库的功能。

顺便说一句,如果你想在不使用c标准库的情况下在Windows中执行上述操作,请留意WriteFile和GetStdHandle函数。虽然不会像linux解决方案那样l33t。

答案 2 :(得分:4)

非常感谢大家的回答。我在问题下面的郝先生的评论中找到了一个简单的答案。他的回答是这样的简单程序

Turbo C(DOS程序):

char far* src = (char far*) 0xB8000000L; 
*src = 'M'; 
src += 2; 
*src = 'D'; 

或试试这个:http://en.wikipedia.org/wiki/Brainfuck :) - //好(一小时前)

我在Turbo C及其工作中尝试过。 我想要一个像这样的简单解决方案,我想接受它作为正确的答案,但他(郝)给它作为评论,所以我粘贴在这里让其他用户代表他知道并接受它。再次感谢郝先生。

答案 3 :(得分:1)

C标准库(请参阅https://en.wikipedia.org/wiki/C_standard_library)具有一组输入和输出例程,用于从各种输入和输出资源读取和写入数据。 C标准库通常基于目标操作系统提供的系统服务和系统调用建立,尽管在没有操作系统的嵌入式微控制器的情况下,将使用不同的方法。

除了C标准库外,还有其他常用的库,例如POSIX库(请参见https://en.wikipedia.org/wiki/C_POSIX_library)。

我使用资源一词是因为输入请求或输出请求的目标可能是各种各样的东西。

  • 磁盘上的文件

  • 网络连接

  • 控制台设备

  • 串行通信端口

  • 传感器

  • 打印机设备

  • 屏幕上的窗口

C标准库采用的模型与Unix操作系统的模型相似,因为所有各种资源都被视为一种设备,您可以从中读取字符或字节流,并写入字符或字节。

在某些情况下,这是抽象概念,可让您忽略资源物理连接的详细信息。因此,您可以打开SATA硬盘,USB拇指驱动器或网络服务器上的文件。无论打印机是在串行通讯端口,USB端口还是网络打印机上,都可以打印到打印机。

对于某些类型的资源,例如控制台设备或具有行和列且可以移动的光标的打印机,通常会在写入设备的字符中提供光标定位信息。因此,您既要输出要在控制台上打印的文本,又要输出将光标定位在要编写的位置的转义码或其他操作,例如突出显示文本。

一个这样的控制台设备是DEC的VT100终端(请参阅https://en.wikipedia.org/wiki/VT100),该终端在输出中使用特殊的转义码来完成诸如将光标定位在屏幕上的操作。这样非常方便,Unix,Linux和Windows上的控制台窗口使用类似的转义码在控制台或命令窗口上执行类似的操作(请参见How to make win32 console recognize ANSI/VT100 escape sequences?)。

C标准库为各种设备提供了标准接口,由编写该库的人员提供该库实际进行读写操作所需的基础功能。

但是,标准库确实存在字符流的限制,这是它使用或呈现给程序员的模型的一部分。这就是为什么存在其他一些库(它们不属于C标准库的一部分)的原因,这些库不是来自图形用户界面和游戏的C标准库,例如来自Microsoft,Qt以及各种其他组(例如OpenGL)(请参见https://en.wikipedia.org/wiki/OpenGLhttps://en.wikipedia.org/wiki/DirectXhttps://en.wikipedia.org/wiki/Graphical_user_interfaceWhat is Linux’s native GUI API?)。另请参见How are GUI's really made?How does an operating system draw windows on the screen?

如果要绕过C标准库并直接使用操作系统I / O系统调用或服务,则可以这样做。但是,与C标准库不同,C标准库是满足C标准要求的所有编译器的标准库,操作系统的I / O服务因操作系统而异。而且某些操作系统可能有几种执行相同类型I / O的方式。例如,Windows有多种执行文件I / O的方法(请参见https://en.wikipedia.org/wiki/Windows_API)。

在某些情况下,您可以绕过操作系统并直接与设备或资源对话。这通常是通过嵌入式应用程序完成的,并且在许多情况下是通过某些微控制器上的嵌入式应用程序完成的,没有真正的操作系统可用,您必须直接与设备进行交互。

微控制器上的嵌入式应用程序通常使用特定的存储器地址与传感器进行交互,以准备传感器进行传感以及从传感器读取温度等数据。传感器具有多种不同的连接方法,这要求程序员了解有关电气设置和用于与传感器通信的协议的知识,例如I2C(请参见https://en.wikipedia.org/wiki/I²C),1-wire(请参见{{3 }})和其他

在旧的MSDOS操作系统下,您可以调用BIOS例程来直接与包括屏幕在内的设备进行交互。或者,如果您知道屏幕缓冲区的地址和内存区域的正确格式,则可以通过直接写入屏幕帧缓冲区所在的内存区域来修改屏幕上显示的内容。

现代多线程和多处理操作系统在其系统调用中具有复杂的功能,可以处理多种尝试使用相同设备和资源的应用程序可能出现的同步和协调问题。由于C标准库是建立在这些操作系统服务之上的,因此,当您使用C标准库时,会获得诸如文件锁定之类的复杂功能。通过标准库使用操作系统服务,您将获得完成仅可使用的工作的专家的专业知识和知识。

现代操作系统提供了多种服务,例如文件I / O,网络I / O,打印服务等。C标准库以及其他组(例如POSIX)的其他库提供了一种标准的可移植方式来访问这些服务。

当将C标准库和POSIX库移植到微控制器时,您便可以访问相同的功能,而无需编写自己的库而需要大量的学习。