C. 编码标准#

编码标准对于评分很重要。我们想强调,除了能得到高分成绩外,良好的编码习惯将改善您的代码质量。这使您的合作伙伴更容易与之互动,最终会增加您获得良好的工作程序。前面曾经说过,本文档的其余部分将讨论编码标准将如何影响评分。

C.1 风格#

就评分而言,风格就是指的代码可读性。至少,这意味着您的代码格式正确、变量名是描述性的、函数已分解,并有友好的注释。任何使读者在阅读或使用您的代码时感到困难(或容易)的因素将反映在您的风格得分中。

现有的Pintos代码是以GNU风格编写的,并且很大程度上遵循GNU编码标准。 我们鼓励您也遵循它们的适用部分,尤其是第5章“充分利用C”。使用不同的样式不会导致实际的问题,但是看到一个函数到另一个函数的样式存在巨大差异是很丑陋的。如果您的代码太丑陋,您将失去不少积分。

请将C源文件行的长度限制为最多79个字符。

Pintos注释有时通过在方括号内写一个名称来引用外部标准或规范,例如:[IA32-v3a]。这些名称是指本文档中使用的参考名称(请参见[参考书目]部分)。

如果您删除现有的Pintos代码,请从您的源文件中完全删除它。不要只是将其放入注释或条件编译指令中,因为这会使生成的代码难以阅读。

我们只在要提交的项目的目录中进行编译。您无需确保先前的项目也可以编译。

应该编写项目代码,以便该项目的所有子问题都可以一起发挥作用,也就是说,无需使用定义的不同宏进行重建等。如果您进行额外的功劳更改正常的Pintos行为以干扰评分,那么您必须实现它,以便仅在给定特殊命令行选项-name的形式时才起作用,其中name是您选择的名称。您可以通过修改“threads/init.c”中的“parse_options()”来添加这样的选项。

简介介绍了其他编码样式要求(请参见1.2.2 设计)。

C.2 C99#

Pintos源代码使用了“C99”标准库中的一些功能,而该功能不在C的原始1989年标准中。许多程序员都不知道这些功能,因此我们将对其进行描述。 Pintos中使用的新功能大部分位于新的头文件中:

<stdbool.h>

定义宏bool,这是一种1位类型,仅采用值0和1,true扩展为1,而false扩展为0。

<stdint.h>

在支持它们的系统上,此头文件为 n = 8、16、32、64以及可能的其他值定义类型intn_tuintn_t。 这些是2的补码有符号和无符号类型,具有给定的位数。

在可能的系统上,此头文件还定义类型“intptr_t”和“uintptr_t”,它们是足以容纳指针的整数类型。

在所有系统上,此头文件定义类型“intmax_t”和“uintmax_t”,它们是系统具有最大范围的有符号和无符号整数类型。

对于此处定义的每个带符号整数类型“type_t”以及“”中定义的“ptrdiff_t”,此头文件还定义了给出类型范围的宏“TYPE_MAX”和“TYPE_MIN”。类似地,对于此处定义的每个无符号整数类型“type_t”以及在中定义的“size_t”,此标头都定义了一个TYPE_MAX宏,以提供其最大值。

<inttypes.h>

”没有提供直接的方法来格式化它用printf()和相关函数定义的类型。此头文件提供了宏来帮助您解决此问题。 对于由“”定义的每个“intn_t”,它都提供宏“ PRIdn”和“ PRIin”,用于用“%d”和“%i”格式化该类型的值。 类似地,对于每个uintn_t,它提供PRIonPRIunPRIuxPRIuX

您可以利用C编译器将相邻的字符串文字串联在一起的事实来使用这些类似的东西:

#include <inttypes.h>
...                  
int32_t value = ...;
printf ("value=%08"PRId32"\n", value);                       |

PRI宏不提供“%”。如上所示,您可以自己提供它,并在其后跟随任何标志,字段宽度等。

<stdio.h>

printf()函数具有一些用于打印标准类型的新类型修饰符:

“j” 用于 intmax_t (e.g. “%jd”) or uintmax_t (e.g. “%ju”).

“z” 用于 size_t (e.g. “%zu”).

“t” 用于 ptrdiff_t (e.g. “%td”).

Pintos的printf()还实现了一个非标准的“'”标志,该标志将大量数字用逗号进行分组,以使其更易于阅读。

C.3 不安全的字符串函数#

众所周知,标准头文件“”和“”中声明的一些字符串函数是不安全的。Pintos C库中故意不包括最严重的几个:

strcpy

注意:如果不慎使用该函数,可能会溢出为输出字符串保留的缓冲区。使用strlcpy()代替。请参阅lib/string.c中源代码中的注释。

strncpy

该函数可能使得目标缓冲区没有空字符串终止符。它还存在性能问题。同样,使用strlcpy()

strcat

strcpy()相同。 使用strlcat()代替。 同样,请参考lib/string.c中源代码中的注释。

strncat

其缓冲区大小参数的含义令人惊讶。 同样,使用strlcat()

strtok

使用全局数据,因此在线程程序(例如内核)中是不安全的。 请改用strtok_r(),并在lib/string.c中查看其源代码以获取文档和示例。

sprintf

strcpy()相同。 使用snprintf()代替。 有关文档,请参见lib/stdio.h中的注释。

vsprintfstrcpy()相同。 改用vsnprintf()

如果您尝试使用这些函数中的任何一个,则会有类似dont_use_sprintf_use_snprintf这样的消息提醒您。