realloc函数的使用

realloc()函数是一个C语言的库函数,定义在头文件<stdlib.h>里。之前一直忽略这个函数的存在,直到最近看The Practice of Programming才学会使用这个函数,小结一下。先来看看realloc()函数的原型。

void *realloc(void *p, size_t size);

realloc()函数的作用是调整malloc()函数动态分配的内存空间大小。如果操作是扩大分配,且调用成功,则原来部分的内容被保留;如果操作是减少分配,且调用成功,则靠后面部分的内容丢失,而前面部分的内容仍保留。

有了这些特点,可以使用realloc()函数实现动态数组,类似C++的vector的功能,开发者无需触碰底层的内存管理问题。我以前曾经想过先使用free()函数释放原来分配的内存,然后重新调用malloc()分配更大的内存。但是实践证明,这种方法效率很低,因为每次都要拷贝内存中原有的内容。

使用realloc()函数,要注意不能马上用原来的指针变量保存新的返回值,如下面的例子。

p = realloc(p, newsize);

万一realloc()分配失败,返回NULL,则旧的内存空间指针会丢失。正确的使用方法如下。

void *tempPtr;
tempPtr = realloc(p, newsize);
if (tempPtr == NULL) {
    /* Handle error */
}
p = tempPtr;

先使用一个临时指针保存重新分配的结果,并且检查是否NULL,然后如果没问题再赋给原来的指针变量。

Advertisements

为什么返回字符指针

很多C语言的函数,比如strcpy或者socket编程中的ntop函数等,最终的结果是得到一个字符串。比如我们要复制一个字符串,可以这样写

char buf[30];
strcpy(buf, src);

但是之前我一直不是很明白为什么要返回char*,指向的也是buf。不过现在终于明白了,因为这样的话,可以直接用在其他有char*参数的函数之中,比如printf系列的函数当中。这样的结果就是可以省去很多不必要的中间变量,而且整段代码也会显得比较简洁。

其实最近很想写日志,包括上次ACM/ICPC的世界决赛的观后感,还有最近很多新闻,无奈整天敲键盘写论文已经令到手指没有太多感觉。

最近比较期待Windows XP的SP3和新的Ubuntu的出现,或者到时重装系统吧。

UNP里学了两招

最近在看《Unix Network Programming》的时候学到了两招,一个是errno的用法,另一个是getenv函数。

errno是一个全局整形变量,我的理解是它定义在<errno.h>里。通常,C语言中函数调用失败都会返回-1或者NULL值。其实,函数除了返回一个表示出错的值外,通常还会把全局变量errno设为一个特定的值,每个操作系统都会把错误值的常量放在<errno.h>。

我们可以在函数返回错误的时候,把errno打印出来,再对着<errno.h>或者使用man命令看看到底是什么错误。比如在Ubuntu最常见是Permission denied。其实标准库也提供打印errno含义的函数,最近就是学到这个,是一个定义在<stdio.h>的函数,叫perror。perror接受一个char*字符串参数,先打印字符串,加个冒号,再打印errno值这时的含义。下面举个例子:

if (socket(AF_INET, SOCK_STREAM, 0) == -1) {
	perror("socket error");
	exit(1);
}

 

第二招是getenv函数。以前也是在附录看过这个函数,但不知道有什么用,原来函数名里env表示enviroment环境变量。使用这个函数,比如getenv(“BERRY”)就能获得环境变量BERRY的值,如果该环境变量没有定义,会返回NULL。至于去获得环境变量的值有什么用,我暂时也不是很了解,估计很多多平台的程序都会使用到这个函数。顺便一提,在Linux中,建立和修改环境变量用export命令,撤销环境变量用unset命令。