1、前言
指针、结构体、联合体、动态内存分配及类型名生命(typedef)是创建C数据类型和算法的基本元素。尽管这些是经常在代码中遇见的,但是其用法的规范性、效率及代码的优化行仍然是大部分程序员所忽视的。所有有必要和大家讨论下这些问题,以提高代码的编写质量。
2、指针
指针在C语言中的用法大概可以分为以下几类:
创建链式数据结构
引用动态分配的数据结构
实现引用调用
访问和遍历数据集合
传递数组参数
作为函数的引用
作为其他数值的别名
表示字符串
直接访问系统内存
2.1 链式数据结构
在底层,指针就是一个内存地址,最适合表示数据结构中各元素的链接,在概念层,链表、树、队列、堆栈和图等等都会用到指针。具体了解请看本博客内的C算法精解部分。
2.2 数据结构的动态分配
指针通过用来存储数据结构的起始地址,在数据结构中用到的很多,基本上都是动态创建C结构体,用来穿件链式数据结构。在这种情况下,指针存储分配给该结构体的内存单元地址。下面是链表中动态申请内存地址的例子:
/* Allocate storage for the element */
if ((new_element = (ListElmt *)malloc(sizeof(ListElmt))) == NULL){
return -1;
}
主要是申请结构体大小的内存空间,用来存储结构体数据。返回是结构体的起始地址。如果在程序使用动态分配很多时,可以定义如下的宏:
#define new(type) (type *)malloc(sizeof(type)
这样可以提高编程质量
2.3 引用调用
指针还经常用于引用方式(by reference)传递参数的函数当中。通过引用方式传递的参数
可以用来返回函数的执行结果,或者减少参数赋值所带来的开销。如果是指针类型的参数
用来返回函数的执行结果,则可以在函数体内发现对该参数的赋值结果操作。例如下面的
例子:}
int
getGidByName(char *name,int *gid){
[...]
*gid = ptr->gid;
return 0;
}
这个函数的返回值仅用来表明函数的出错情况。
指针类型的参数通常用来避免调用过程中大型数据元素复制的开销,在函数参数中实现结构体指针。这种使用在编程中经常的用到,这里就不在介绍了。
2。4 数据元素的访问
在指向数组元素的指针可以用来访问特定索引位置的数组元素,并且使用指向数组元素的算术元素和数据的索引的算是元素具有相同的语义。下面是strcpy函数原型:
char* strncpy(char *dest, const char *src, size_t n){ size_t i;
for (i = 0 ; i < n && src[i] != '\0' ; i++) dest[i] = src[i]; for ( ; i < n ; i++) dest[i] = '\0';
return dest; }
(