在C语言中,“正确返回字符串”的方法并不存在。在C语言中,一个“字符串”是一个字符数组(包括空字符),并且数组本身不能从函数中返回。
函数可以返回指针。因此,“返回字符串”的常规方法是:
1. 返回指针。例如`char *strdup()`,函数声明为`char *foo1(...)`。
2. 传递指向字符数组的指针并修改其内容。例如`int sprintf(char *dest, const char *format, ...)`,函数声明为`void foo2(char *,...)`。
3. 结合1和2,例如`char *strcpy(char *dest, char *src)`,函数声明为`char *foo3(char *, ...)`。
4. 传递指针的地址并进行更新。例如`ssize_t getline(char **lineptr, size_t *n, FILE *stream)`,函数声明为`foo4(char **ptr)`。
关键是指针相关联的内存必须在函数完成后保持有效。返回指向函数非静态内存的指针是未定义的行为。成功的方法包括调用代码传递指针,或函数通过分配内存为某些持久值(如全局变量或字符串常量)提供指针。
当前设计惯例鼓励像上述2和3那样的函数还提供`size_t size`,以便函数了解可用内存的限制。
char *foo2(char *s, size_t size, const pkg_T *pkg) {
int result = snprintf(s, size, "%02x:%02x:%02x:%02x:%02x:%02x",
pkg->address[0], pkg->address[1], pkg->address[2],
pkg->address[3], pkg->address[4], pkg->address[5]);
if (result < 0 || result >= size) return NULL;
return s;
}
另一种方法是分配内存(我倾向于使用上述方法)。这需要调用代码使用
free()
释放内存。
#define UINT_MAX_WIDTH (sizeof(unsigned)*CHAR_BIT/3 + 3)
char *foo2alloc(char *s, size_t size, const pkg_T *pkg) {
char buf[(UINT_MAX_WIDTH+3)*6 + 1];
int result = snprintf(buf, sizeof buf, "%02x:%02x:%02x:%02x:%02x:%02x",
pkg->address[0], pkg->address[1], pkg->address[2],
pkg->address[3], pkg->address[4], pkg->address[5]);
if (result < 0 || result >= size) return NULL;
return strdup(buf);
}