在C中返回字符串的正确方法

mst*_*agg 5 c string pointers

我有以下代码:

char* get_address_string(PACKAGE* pkg){
    char *c;
    sprintf(c, "%02x:%02x:%02x:%02x:%02x:%02x", pkg->address[0], pkg->address[1], 
        pkg->address[2], pkg->address[3], pkg->address[4], pkg->address[5]);
    return c;
}
Run Code Online (Sandbox Code Playgroud)

代码工作正常.但是,我知道这不是在C中返回字符串的正确方法.我收到警告"c在此函数中使用未初始化".

在C中编写此函数的正确方法是什么?

chu*_*ica 9

"在C中返回字符串的正确方法"并非真正可行.在C中,字符串是一个字符数组(直到并包括空字符),并且数组本身不能从函数返回.

函数可以返回指针.所以通常的方法是"返回一个字符串":

  1. 返回一个指针. char *foo1(...)喜欢char *strdup()

  2. 传入指向字符数组的指针并修改其内容.void foo2(char *,...)喜欢int sprintf(char *dest, const char *format, ...)

  3. 结合1和2之char *foo3(char *, ...) 类的char *strcpy(char *dest, char *src)

  4. 传递指针的地址并更新它.foo4(char **ptr)喜欢ssize_t getline(char **lineptr, size_t *n, FILE *stream)

关键是在函数完成后,与指针关联的内存必须有效.返回指向函数的非静态内存的指针是未定义的行为.成功的方法包括让调用代码在指针中传递,或者通过内存分配指向一些持久值(如全局变量或字符串常量)的函数来提供它.

在C中编写此函数的正确方法是什么?

目前的设计实践鼓励上面的#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]);
      // encoding error or not enough room
      if (result < 0 || result >= size) return NULL;
      return s;
    }
Run Code Online (Sandbox Code Playgroud)

另一种方法是分配内存(我赞成以上).这要求调用代码到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]);
      // encoding error or not enough room
      if (result < 0 || result >= size) return NULL;
      return strdup(buf);
    }
Run Code Online (Sandbox Code Playgroud)