近日,周立功教授公开了他的心血之作《程序设计与数据结构》。该书的电子版已无偿分享给电子工程师和高校群体。周教授授权我们对本书内容进行连载。
在软件开发过程中,理解和描述问题域是一项重要的思维活动。开发人员通常借助熟悉的自然语言进行思考,而最终的实现则需要用计算机能理解的编程语言来描述。然而,自然语言和编程语言之间存在着显著的差异,这被称为“语言的鸿沟”。这意味着开发人员需要跨越这种鸿沟,将思维语言转化为描述语言,以便机器能够理解和执行。
学习和开发成本高的主要原因在于理解上的困难,因此建立一种通用语言至关重要。这种通用语言不仅是沟通工具,也是自我思维训练和建立逻辑推理的有效手段。
2016年初,几位朋友请求我帮助他们教孩子编程。最初的教学从变量的基本概念开始,比如:
c
int iNum = 0x64;
这段代码包含三个关键部分:变量类型int、变量名iNum和变量值0x64。随后,编写了一个简单的程序,详见程序清单 1.1。
```c
int main(int argc, char *argv[]) { int iNum = 0x64; printf("%x, %xn", &iNum, iNum); return 0; } ```
通过运行结果可以看到,0x64存储在0x22FF74内存单元中。尽管&iNum提供了变量的地址,但&iNum本身是一个较为抽象的概念。当我们将地址形象地称为“指针”时,就可以通过指针找到对应的内存单元。因此,词汇表中新增了“指针”这一概念,例如:
c
int iNum = 0x64;
int *ptr = &iNum;
现在,词汇表中又增加了一个新成员——指针变量ptr,它指向int类型的变量。理解指针的一个有效方法是绘制图表,详见图 1.1。
进一步讨论,既然&iNum可以找到iNum的值,那么如何存储&iNum呢?定义一个存放指针&iNum的变量。例如:
c
int iNum = 0x64;
int *ptr = &iNum;
此时,词汇表中增加了新的成员——指针变量ptr,它指向int类型的变量。如果进一步扩展,可以定义一个指向指针变量ptr的指针,即双重指针。例如:
c
typedef int *PTR_INT;
PTR_INT *pPtr = &ptr;
其中,pPtr是指向PTR_INT类型的指针变量,PTR_INT的类型为int *,因此pPtr是指向int **的指针变量。
假设声明如下:
c
int a[2];
许多人可能会认为a是数组首元素的指针。事实上,数组的类型属于构造类型,需要从不同的角度进行分析。数组名a在声明时、表达式中以及作为&和sizeof操作数时都有不同的含义。
在表达式中,数组名a被解释为指向数组首元素的指针,即a == &a[0]。当a作为&操作数时,&a是指向数组的指针。此外,通过指针运算规则,a + i等于&a[i]。
数组的类型为int [2],因此&a是指向int [2]数组类型的指针,简称数组指针。其类型为int (*)[2],即指向int [2]的指针类型。这种类型约定是为了避免歧义,确保编译器能够正确解析。
为了实现更通用的功能,例如在一个数组中查找特定值,可以使用迭代器。一个通用的查找函数原型如下:
c
int *findValue(int *begin, int *end, int value);
这个函数可以在指定范围内查找值,并返回指向第一个匹配元素的指针。为了使该函数适用于多种数据结构,可以使用迭代器变量表示操作范围。迭代器的基本思想是存储数组中某个元素的位置,从而能够遍历该位置的元素。
为了实现更灵活的机制,可以使用模板函数。模板函数在实现任何地方都不会受限于特定类型,编译器会自动确定数据类型。例如:
c
template <typename Item>
Item max(Item a, Item b) {
if (a > b)
return a;
else
return b;
}
这种模板函数可以处理多种数据类型,提高了代码的灵活性和通用性。
由此可见,C语言有其独特的优势,但C++提供了更大的灵活性和功能。嵌入式系统软件的开发不仅可以用C语言,也可以使用C++。
希望这些内容对你有所帮助!