如果没有 C 中的库函数,如何打印变量的任何字符、字符串或值?
例如,如果我不应该使用 printf()
、putchar()
等标准库函数,那么如何将字符打印到屏幕上?
有没有一种简单的方法可以做到这一点。 我对系统调用不太了解,如果我必须使用它们那么我该如何使用它们? 那么有人可以建议一种不使用库函数的简单打印方法吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在标准 C 中,你不能。 C 中定义的唯一 I/O 是通过 C 标准库函数。
在给定的平台上,可能有多种方法可以做到这一点:
write
调用,而无需使用 C 库。 获取 C 库的源代码以了解它是如何完成的。除非您正在编写自己的 C 库,否则我不确定您为什么要这样做。
In standard C, you can't. The only I/O defined in C is through the C standard library functions.
On a given platform, there may be ways to do it:
write
call directly, without using your C library. Grab the source of your C library to see how it's done.Unless you're writing your own C library, I'm not sure why you'd want to do this.
在 Linux 中,您可以使用
write
系统调用:如果您还觉得不够,您可以低一级,一般调用系统调用:
值得了解
strace< /code>,您可以使用它来查看任何特定程序在运行时使用了哪些系统调用。 但请注意,对于“一些简单的解析器”,几乎不需要使用原始系统调用。 更好地利用c库的函数。
顺便说一句,如果您想在 Windows 中执行上述操作而不使用 c 标准库,请查找 WriteFile 和 GetStdHandle 函数。 不过不会像 linux 解决方案那样 l33t。
In linux, you can use the
write
system-call:If you can't get enough of it, you can go one step lower, invoking the syscall generically:
It's worth knowing about
strace
, which you can use to see which syscalls are used by any particular program while it runs. But note that for "some simple parser", it's hardly needed to use raw system calls. Better use the functions of the c library.By the way, lookout for WriteFile and GetStdHandle functions if you want to do the above in Windows without using the c standard library. Won't be as l33t as the linux solution though.
好的,谢谢大家的回答。我在问题下面的郝先生的评论中找到了一个简单的答案。 他的答案是这样的简单程序
Turbo C(DOS 程序):
或者试试这个:http://en.wikipedia.org/wiki/Brainfuck :) – //Hao(一小时前)
我在 Turbo C 上尝试了一下,它的工作原理。
我想要一个像这样的简单解决方案,我想接受它作为正确答案,但他(Hao)将其作为评论给出,所以我将其粘贴到此处,以便其他用户代表他了解这一点并接受它。 再次感谢郝先生。
Well thank u all for ur answers.I found one simple answer by a comment from Mr. Hao below the question. his answer is simple program like this
Turbo C(DOS program):
or try this: http://en.wikipedia.org/wiki/Brainfuck :) – //Hao (an hour ago)
I tried it on Turbo C and its working.
I wanted a simple solution like this and I wanted to accept it as correct answer but he(Hao) gave it as a comment so I pasted it here for other users to know about this on behalf of him and accepted it. Once again thank u Mr.Hao.
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 上的控制台窗口使用类似的转义码在控制台或命令窗口上执行类似的操作(请参阅 如何使 win32 控制台识别 ANSI/VT100 转义序列?)。
C 标准库为各种设备提供了标准接口,并且由编写该库的人员来提供该库实际进行读写所需的底层功能。
然而,标准库确实存在字符流作为其使用或呈现给程序员的模型的一部分的限制。 这就是为什么还有其他库不属于用于图形用户界面和游戏的 C 标准库的原因,例如来自 Microsoft、Qt 和其他各种团体(例如 OpenGL)的库(请参阅 https://en.wikipedia.org/wiki/OpenGL 、https://en.wikipedia.org/wiki/DirectX , https://en.wikipedia.org/wiki/Graphical_user_interface 和 什么是 Linux 的本机 GUI API?)。 另请参阅 GUI 是如何制作的? 和 操作系统如何在屏幕上绘制窗口?
如果你想绕过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 线(请参阅 https://en.wikipedia.org/wiki/1-Wire )等。
在旧的MSDOS操作系统下,您可以调用BIOS例程直接与包括屏幕在内的设备进行交互。 或者,如果您知道屏幕缓冲区的地址和内存区域的正确格式,则可以通过直接写入屏幕帧缓冲区所在的内存区域来修改屏幕上显示的内容。
现代多线程和多处理操作系统在其系统调用中具有复杂的功能,可以处理由于多个应用程序都试图使用相同的设备和资源而可能出现的各种同步和协调问题。 由于 C 标准库构建在这些操作系统服务之上,因此当您使用 C 标准库时,您将获得复杂的功能,例如文件锁定。 通过标准库使用操作系统服务,您可以获得完成您可以使用的工作的专家的专业知识和知识。
现代操作系统提供了丰富多样的服务,例如文件 I/O、网络 I/O、打印服务等。C 标准库以及来自其他组(例如 POSIX)的其他库提供了一种标准的、可移植的方式来访问这些服务。
当 C 标准库和 POSIX 库移植到微控制器时,您可以通过一种方式访问相同的功能,而无需编写自己的库的巨大学习曲线。
The C Standard Library (see https://en.wikipedia.org/wiki/C_standard_library ) has a set of input and output routines that are used to read from and write to various input and output resources. The C Standard Library is ordinarily built upon the system services and system calls provided by the target operating system though in the case of embedded microcontrollers that do not have an operating system a different approach is used.
In addition to the C Standard Library there are other libraries often used such as the POSIX library (see https://en.wikipedia.org/wiki/C_POSIX_library ).
I use the term resources because the target for an input request or an output request may be a large variety of different things.
a file on a disk
a network connection
a console device
a serial communications port
a sensor
a printer device
a window on a screen
The model adopted by the C Standard Library is similar to that of the Unix operating system in that all of the various kinds of resources are treated as a device from which you read a stream of characters or bytes and you write a stream of characters or bytes.
In some cases this is abstraction allows you to ignore the details of physical connectivity of the resource. So you can open a file on a SATA hard disk, or a USB thumb drive, or a network server. You can print to a printer whether the printer is on a serial communications port, or a USB port, or a network printer.
For some types of resources such as a console device or a printer which has rows and columns and a cursor that can be moved, you would ordinarily provide the cursor positioning information within the characters you write to the device. So you would output both the text you want to print on the console as well as escape codes that would position the cursor where you want to write or some other action such as highlighting text.
One such console device was the VT100 terminal from DEC (see https://en.wikipedia.org/wiki/VT100 ) which used special escape codes in the output to do things like position the cursor on the screen. This was so handy that console windows on Unix, Linux, and Windows use similar escape codes to do similar actions on console or command windows (see How to make win32 console recognize ANSI/VT100 escape sequences?).
The C Standard Library provides a standard interface to a wide variety of devices and it is up to the people who wrote the library to provide the underlying functionality that the library needs to actually do reading and writing.
However the Standard Library does have the limitation of streams of characters as part of the model that it uses or presents to the programmer. That is why there are other libraries that are not part of the C Standard Library for graphical user interfaces and games such as from Microsoft, Qt, and various other groups such as OpenGL (see https://en.wikipedia.org/wiki/OpenGL , https://en.wikipedia.org/wiki/DirectX , https://en.wikipedia.org/wiki/Graphical_user_interface , and What is Linux’s native GUI API? ). See as well How are GUI's really made? and How does an operating system draw windows on the screen?
If you want to bypass the C Standard Library and use the operating system I/O system calls or services directly, you can do so. However unlike the C Standard Library which is standard across compilers that meet the C Standard requirements, the operating system I/O services will vary from operating system to operating system. And some operating systems may have several ways to do the same kind of I/O. For instance Windows has a number of different ways to perform file I/O (see https://en.wikipedia.org/wiki/Windows_API ).
In some cases you can bypass the operating system and talk directly to the device or resource. This is often done with embedded applications and in many cases with embedded applications on some microcontrollers, there is no real operating system available and you must interact directly with the device.
Embedded applications on microcontrollers often use specific memory addresses to interact with sensors in order to prepare the sensor for sensing as well as to read data such as temperature from the sensor. Sensors have a number of different connectivity methods which requires the programmer to know something about the electrical setup and the protocol to be used to talk with the sensor such as I2C (see https://en.wikipedia.org/wiki/I²C ), 1-wire (see https://en.wikipedia.org/wiki/1-Wire ) and others.
Under the old MSDOS operating system you could call BIOS routines to directly interact with devices including the screen. Or if you knew the address of the screen buffers and the proper format for the memory area, you could modify what was displayed on the screen by writing directly into memory areas where the screen frame buffers were located.
Modern multi-threading and multi-processing operating systems have sophisticated functionality within their system calls to handle the kinds of synchronization and coordination problems that can arise with multiple applications all trying to use the same devices and resources. Since the C Standard Library is built on top of these operating system services, when you use the C Standard Library you get that sophisticated functionality such as file locking. And using operating system services through the Standard Library you get the expertise and knowledge of experts who have done the work that you can just use.
Modern operating systems provide a rich variety of services such as file I/O, network I/O, printing services, etc. The C Standard Library along with other libraries from other groups such as POSIX provide a standard, portable way to access those services.
And when the C Standard Library and the POSIX library are ported to microcontrollers, you have a way of accessing this same functionality without having the huge learning curve of having to write your own library.