当前位置:  开发笔记 > 编程语言 > 正文

如果没有"std",你能用C做什么包括?它们是"C"的一部分还是仅仅是图书馆?

如何解决《如果没有"std",你能用C做什么包括?它们是"C"的一部分还是仅仅是图书馆?》经验,为你挑选了4个好方法。

如果这是一个主观或重复的问题,我道歉.搜索有点尴尬,所以我不确定要包含哪些术语.

我想知道的是当你不包括像stdio和的标准库时,C语言中的基础工具/功能是什么stdlib.

如果没有printf(),我该怎么办fopen()

另外,这些库在技术上是"C"语言的一部分,还是只是非常有用且有效的基本库?



1> Steve Jessop..:

C标准就是这样说的(5.1.2.3/5):

符合实施的最低要求是:

- 在序列点处,易失性对象在先前访问完成且后续访问尚未发生的意义上是稳定的.

- 在程序终止时,写入文件的所有数据应与根据抽象语义产生的程序执行的结果相同.

- 交互设备的输入和输出动态应按照7.19.3的规定进行.

因此,如果没有标准库函数,程序保证具有的唯一行为与易失性对象的值有关,因为您不能使用任何保证文件访问或"交互设备"."Pure C"仅通过标准库函数提供交互.

但是,Pure C并不是全部,因为您的硬件可能具有某些地址,这些地址在读取或写入时会执行某些操作(无论是SATA或PCI总线,原始视频内存,串行端口,还是要发出哔哔声,或者闪烁的LED).因此,了解您的硬件,您可以在不使用标准库函数的情况下在C中进行大量编写.可能您可以实现C标准库,尽管这可能需要访问特殊的CPU指令以及特殊的内存地址.

但是在纯C中,没有扩展,并删除了标准库函数,除了读取命令行参数,做一些工作,并从中返回状态代码之外,你基本上不能做任何事情main.虽然你的唯一资源是自动和静态变量,没有堆分配,但它仍然没有被嗅到,它仍然是图灵完全受资源限制.它不是一个非常丰富的编程环境.

标准库是C语言规范的一部分,但在任何语言中都倾向于在"如此"的语言和库之间划线.这是一个概念上的差异,但最终在原则上并不是一个非常重要的差异,因为标准说他们聚在一起.任何做非标准事情的人都可以像删除图书馆一样轻松删除语言功能.无论哪种方式,结果都不是C的一致实现.

请注意,C的"独立"实现只需要实现标准的子集,包括不包括任何I/O,因此您处于我上面描述的位置,依赖于特定于硬件的扩展来完成任何有趣的事情. .如果你想根据标准区分"核心语言"和"库",那么这可能是绘制线的好地方.



2> plinth..:

你能做什么?一切!

除了预处理器之外,C中没有魔法.

最难的,也许是写putchar - 因为这是平台相关的I/O.

创建自己的varargs版本是一个很好的本科练习,一旦你有了它,你可以使用自己的vaprintf版本,然后是printf和sprintf.

1986年,当我对使用Lightspeed C提供的stdio例程不满意时,我在Macintosh上完成了所有操作 - 使用win_putchar,win_printf,in_getchar和win_scanf编写了我自己的窗口处理程序.

整个过程称为bootstrapping,它可以是编码中最令人满意的体验之一 - 使用基本设计,具有相当大的实际意义.


你不能.putchar接受一个角色写出来 - 在哪里?嗯,这是一个实现细节.在嵌入式系统上,它可能是一个串口,因此putchar看起来像void putchar(char c){*addressOfOutPort = c; 在我写的Macintosh代码中,它在我想要的角色位于适当位置和滚动的窗口中.
@WhirlWind - 通过将`char*`数据转换为函数指针,您可以在基本上任何系统上嵌入并执行C中的任意汇编代码.
哦,停止在假设中说话 - 很容易检查!:-)在Google代码搜索中,输入"putchar" - 第一个结果是GNU libc的putchar(),它是用C语言编写的.它调用`_IO_putc_unlocked`,这是一个在内部结构上执行一些指针运算的宏.

3> Michael Burr..:

如果您不需要它们,您当然没有义务使用标准库.相当多的嵌入式系统要么没有标准库支持,要么因某种原因无法使用它.该标准甚至专门讨论了没有库支持的实现,C99标准5.1.2.1"独立环境":

在独立环境中(可以在没有操作系统任何好处的情况下执行C程序),程序启动时调用的函数的名称和类型是实现定义的.除了第4节要求的最小集合之外,任何可用于独立程序的库设施都是实现定义的.

通过C99所要求的报头是在一个独立的实行都可以,, , , , ,和.这些头只定义类型和宏,因此不需要函数库来支持它们.

如果没有标准库,您完全依赖于您自己的代码,可能可用的任何非标准库,以及您可能能够与之交互的任何操作系统系统调用(可能被视为非标准库)调用).很可能你必须让你的C程序调用程序集例程来连接设备和/或平台上的任何操作系统.



4> Calmarius..:

如果没有printf(),fopen()等,我该怎么办?

只要您知道如何连接您正在使用的系统,您就可以在没有标准C库的情况下生存.在只有几千字节内存的嵌入式系统中,您可能根本不想使用标准库.

这是一个Hello World!不使用任何标准C函数的Linux和Windows上的示例:

例如,在Linux上,您可以直接在内联汇编中调用Linux系统调用:

/* 64 bit linux. */

#define SYSCALL_EXIT 60
#define SYSCALL_WRITE 1

void sys_exit(int error_code)
{
    asm volatile
    (
        "syscall"
        : 
        : "a"(SYSCALL_EXIT), "D"(error_code)
        : "rcx", "r11", "memory"
    );
}

int sys_write(unsigned fd, const char *buf, unsigned count)
{
    unsigned ret;

    asm volatile
    (
        "syscall"
        : "=a"(ret)
        : "a"(SYSCALL_WRITE), "D"(fd), "S"(buf), "d"(count)
        : "rcx", "r11", "memory"
    );

    return ret;
}

int _start()
{
    const char hwText[] = "Hello world!\n";

    sys_write(1, hwText, sizeof(hwText));
    sys_exit(12);

    return 0;
}

用以下内容编译:

gcc -nostdlib nostd.c 

它输出Hello world!并退出.

在Windows上,系统调用不会被发布,而是隐藏在另一个抽象层kernel32.dll之后.无论您是否想要,程序启动时始终会加载哪个.所以你可以简单地包含windows.h并使用Win32 API:

#include 

int _start()
{
    const char str[] = "Hello world!\n";
    HANDLE stdout = GetStdHandle(STD_OUTPUT_HANDLE);
    DWORD written;

    WriteFile(stdout, str, sizeof(str), &written, NULL);
    ExitProcess(12);

    return 0;
}

windows.h与标准C库无关,因为您应该能够使用任何其他语言编写Windows程序.

您可以使用MinGW工具编译它,如下所示:

gcc -nostdlib C:\Windows\System32\kernel32.dll nostdlib.c

然后编译器足够聪明,可以解析导入依赖项并编译程序.

如果你反汇编程序,你只能看到你的代码在那里,其中没有标准的库膨胀.

因此,您可以在没有标准库的情况下使用C.

推荐阅读
wurtjq
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有