话题 2 开始接触标准库——封装好的标准函数集合。Guide to C stdlib functions 针对 C 标准库中可用的函数提供了一份很好的概述。

许多程序员只是将标准库看作一个“黑匣子”——按文档说明使用函数,但对底层的实现并不清楚。鉴于本课程的目标是让大家真正了解系统的内部运作方式,所以我们将进行更深入的研究。

为此,我们提供了一些练习,深入研究标准库的代码。通过研究工业级代码,并反思其在设计、可读性和效率之间的权衡,我们可以学到很多东西。深入了解这些函数的底层实现,我们还可以更好地使用这些函数,并避免一些陷阱和误用。

这些知识也可能会激发你写出自己的 isdigitstrncpy 函数,并集成到你的程序中,但最佳实践是尽可能选择标准库函数。这些函数已经编写完成,并且经过了充分的调试和验证——有什么理由不去使用它们呢?我们从代码中学习这些函数的实现,对一些不好的设计提出自己的见解和批评,但在以后使用它们时,也应该心存感激。

本次实验进一步练习使用 gdbValgrind、学习 string.h 接口以及将 C 字符串作为原始数组/指针进行操作。以下一些问题用于检测你的理解,并让你进一步思考这些概念:

  • strncpy 的调用,在什么情况下会以空字符 NUL\0)作为目标字符串的结尾,在什么情况下不会?使用未以 NUL 字符结尾的字符串会产生哪些后果?
  • 一个程序直接运行时看起来没什么问题,但是在 Valgrind 下运行时,它会报告错误。你的伙伴认为 Valgrind 的报告大错特错,而且非常偏执地认为程序运行正常就说明没有问题。向他们解释为什么访问不属于你的内存时会造成问题,并进一步描述即便发生了错误,为什么内存错误可以无症状地潜伏在程序中。
  • 编写一个 C 表达式判断给定的 char* 是否包含 N 个字符长的前缀/后缀。请务必利用 string.h 库函数。如果使用比字符串长度更长的 N 值来计算表达式,会发生什么情况?
  • 函数 atoi/strtol 将数字字符串转换为十进制数字,但没有标准函数可以反向转换。描述一种可用于将数字转换为等效字符串的技术。

学习目标

  • 研究数组和指针在 C 中如何工作
  • 阅读并分析操作 C 字符和字符串的代码
  • 使用 gdbValgrind 检测和调试内存错误

初始代码

你的个人用户目录下应该已经有 cs102 这个文件夹了,通过下面的命令拷贝初始代码到该目录中:

cp -r /home/cs102-shared/labs/lab2 ~/cs102