一、解决函数返回指针的几种方法
1. 返回一个指向字符串常量的指针。
例子:
char* func() { rturn "Only work for simple strings"; }
优点:简单
缺点:如果你需要计算字符串的内容,这种方法就无能为力了。如果以后需要修改返回的字符串,你也会遇到麻烦!
2. 使用全局声明的数组。
例子:
char my_global_array[255]; char* func() { my_global_array[0] = '0'; return my_global_array; }
优点:适用于自己创建的字符串,简单易用。
缺点:任何人都有可能在任何时候修改这个全局数组,而且该函数的下一次调用也会覆盖该数组的内容。
3. 使用静态数组。
例子:
char* func() { static char buff[20]; buff[0] = '0'; return buff; }
优点:可以防止任何人都修改这个数组,只有拥有指向该数组的指针的函数(通过参数传递给它)才能修改这个静态数组。
缺点:但是,该函数的下一次调用将覆盖这个数组的内容,所以调用者必须在此之前使用或备份数组的内容。和全局数据一样,大型缓冲区如果闲置不用是非常浪费内存空间的。
4. 显式地分配一些内存,保存返回的值。
例子:
char* func() { char *s = malloc(120); ... return s; }
优点:这个方法具有静态数组的优点,而且在每次调用时都创建一个新的缓冲区,所有该函数以后的调用不会覆盖以前的返回值。它适用于多线程的代码。
缺点:程序员必须承担起内存管理的责任。
5. 要求调用者分配内存类保存函数的返回值。程序员 malloc 和 free
例子:
void func(char* result, int size) { ... strncpy(result, "that'd be in the data segment, Bob", size); } buffer = malloc(size); func(buffer, size); ... free(buffer);
优点:内存管理比较轻松。
缺点:程序员还是需要自己管理内存,但是相比起第4种方法而言,malloc和free成对出现,管理内存会更方便。
二、关于声明
2.1 一些不能
1. 函数的返回值不能是一个函数;foo() ()是非法的。
2. 函数的返回值不能是一个数组;foo()[0]是非法的。
3. 数组里面不能有函数;foo[]()是非法的。
三、关于函数参数传递
有些C语言书籍声称“在调用函数时,参数按照从右到左的次序压到堆栈里。”这样的说法过于简单了。其实,参数在传递时首先尽可能地存放到寄存器中(为了追求速度)。
注意:int型变量i和包含一个int型成员的结构(struct)变量s在参数传递时的方式可能完全不同。一个int型变量参数一般会被传递到寄存器中,而结构参数则可能被传递到堆栈中。
四、define和typedef的区别
4.1 其一
define只是文本替换
而typedef却不只是文本替换。typedef是一种彻底的“封装”类型——在声明它之后不能再往里面增加别的东西。如:
#define peach int
unsigned peach i;//No problem.
typedef int banana;
unsigned banana i;//Error.
4.2 其二
在连续几个变量的声明中,用typedef定义的类型能够保证声明中所有的变量均为同一种类型,而用#define定义的类型则无法保证。
#define int_ptr int *
int_ptr chalk, cheese; //as int * chalk, cheese; means chalk is a pointer, cheese is int.
typede int* int_ptr;
int_ptr chalk, cheese;//two pointer.