C 为什么不需要提供托管环境?
C11标准规定: §5.1.2.2托管环境C 为什么不需要提供托管环境?,c,language-lawyer,C,Language Lawyer,C11标准规定: §5.1.2.2托管环境 无需提供托管环境,但应符合以下规范(如有) 我很困惑,没有执行环境我怎么能执行一个程序?这是否意味着托管环境不是必需的,而独立环境是必需的 我很困惑,我怎么能在没有 执行环境 “托管”基本上是指具有底层操作系统。然而,考虑到C的目标,需要一个目标可能非常有限。考虑许多微控制器或实时系统:唯一运行的程序是编码的,因此没有限制;这就是为什么说它是独立的 正如N1124所言(强调我的) 在独立的环境中(其中C程序执行可能需要 没有任何操作系统好处的地方)
无需提供托管环境,但应符合以下规范(如有) 我很困惑,没有执行环境我怎么能执行一个程序?这是否意味着托管环境不是必需的,而独立环境是必需的 我很困惑,我怎么能在没有 执行环境 “托管”基本上是指具有底层操作系统。然而,考虑到C的目标,需要一个目标可能非常有限。考虑许多微控制器或实时系统:唯一运行的程序是编码的,因此没有限制;这就是为什么说它是独立的 正如N1124所言(强调我的) 在独立的环境中(其中C程序执行可能需要 没有任何操作系统好处的地方)
这是否意味着托管环境不是必需的,而独立环境是必需的
该标准定义了C代码预期运行的两种类型的环境及其要求。独立环境的要求比托管环境低:这可能意味着某些功能可能不可用,而它们将在托管环境中使用,这意味着这是“必要的”拥有一个。托管和免费的静态环境和实现之间的区别在于C标准库的存在。语言功能本身对这两种功能都可用(除了少数可选功能) 但是iff环境称为“托管”,它必须提供标准要求的完整(库)功能。没有半途而废的办法 为托管环境编写的C程序可以预期所有必需的功能都会出现,因此可以使用
malloc
等。一旦缺少此类功能,例如动态内存分配,它就不是托管环境,而是独立的。这并不意味着后者不能提供某些标准库(或其某些功能)。实际上,即使对于独立的环境,也可能存在转换功能
因此,如果没有可用的标准库,程序如何运行?简单地说:它不使用这些函数。相反,它必须使用自己的功能访问底层硬件或专门的非标准库。如果你没有汽车,你必须步行、骑自行车或自己造一辆。您不必使用基本法则,例如printf
,但也可以直接将字符发送到串行接口,或调用OS函数将字符发送到stdout
典型的场景是裸机(即没有成熟的操作系统)嵌入式系统。他们通常不需要打印字符,只需要拨动LED灯、控制电机、通过监控数字输入检测按钮等
正如其他人已经提到的,操作系统是另一个例子。显然,你不能期望操作系统可以用于操作系统,因为没有。独立的环境用于运行程序,这些程序通常与许多程序遇到的情况截然不同。下面是一个最小但有效的C程序的示例,如果编译用于许多PIC处理器(如提供独立环境的PIC 16C84),该程序可以执行有用的功能
// Example of a program for a free-standing environment
int main(void)
{
unsigned char a;
((unsigned char volatile*)0x86) = 3; // Set port B0 and B1 to output
a=0;
while(1)
{
((unsigned char volatile*)0x6) |= 1; // Output high on B0
((unsigned char volatile*)0x6) &= ~1; // Output low on B0
a&=127;
b=++a;
do
{
((unsigned char volatile*)0x6) |= 2; // Output high on B1
((unsigned char volatile*)0x6) &= ~2; // Output low on B1
} while(--b);
}
}
如果要编译此程序并将生成的文件馈送到
设备编程器,这将导致设备在任何时候通电
向上,在引脚B0上输出一个脉冲,然后在B1上输出一个脉冲,然后在B0上输出一个脉冲,在B1上输出两个脉冲,
B0上有一个,B1上有三个,等等。B1上最多有128个,然后图案将
重复一遍
上面的程序不会由任何类型的操作系统启动——它的存储容量为1024条指令和36字节的数据
拉姆:真的没有地方放一个。相反,处理器将把控制权转移到一个小型编译器生成的初始化例程,该例程清除RAM,然后跳转到main,而后main将永远不会返回。然而,缺少操作系统并不是问题,因为程序所需要做的只是晃动几个I/O管脚,它可以通过写入与这些管脚相关的地址来做到这一点
实际上,我不会使用端口地址编写代码,而是使用
编译器提供的头文件,定义所有I/O寄存器的名称,
但是没有它们,代码是有效的。有趣的是,上面的代码不会为其I/O调用任何库函数(或为此调用任何函数),因为硬件会通过改变某些输出管脚的条件来响应写入地址0x86和0x06的尝试,这正是此应用程序所需要的。除了不到十几条编译器生成的启动代码指令外,整个系统中唯一的代码是由上述C生成的机器代码(大约16条指令)。简单地说:托管环境意味着程序在操作系统中运行。“独立式”用于编写操作系统。@Kninnug:不仅仅用于编写操作系统。嵌入式系统通常没有标准库所需的所有功能和/或添加的膨胀没有任何意义。严格来说,gcc也是一个独立的实现。它需要一个C库,比如newlib或glibc。@Kninnug如果一个程序在操作系统中运行,我们可以说“它在托管环境中运行”,对吗?如果是这样,为什么不提供呢?@Kninnug“托管环境”的定义将很有帮助。我搜索过它,但什么也没找到。@Olaf这就是为什么我在它前面加上“非常简单”的前缀;)。不过,操作系统编写是C最初的设计目标之一。GCC不是执行环境,而是翻译环境(C11§5.1.1)。“某些功能可能不可用。”是的,例如