c/c++开发分享在C中返回字符串的正确方法

我有以下代码:

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; } 

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

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

    c是指针,但没有分配内存。 返回值没问题,就是如何在C中完成。

    但是你需要分配内存。

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

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

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

    在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; } 

    另一种方法是分配内存(我赞成以上)。 这迫使调用代码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); } 

    由于c未初始化, sprintf写入未知的内存位置,这会导致未指定的行为。 它可能会立即崩溃,它可能根本不会崩溃,或者它可能会在一些完全不相关的代码行上崩溃。

    您需要通过malloc为其分配内存来初始化指针。

     char* get_address_string(PACKAGE* pkg){ char *c = malloc(20); // enough room for output as 00:11:22:33:44:55 plus null terminator if (c == null) { perror("malloc failed"); exit(1); } 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; } 

    请注意,即使您提前知道需要多少内存,也无法通过数组在编译时将其放在一边。 这是错的:

     char* get_address_string(PACKAGE* pkg){ char c[20]; // allocated on the stack, contents unspecified on return 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; } 

    就是这样:

     char* get_address_string(PACKAGE* pkg){ char c[20]; // allocated on the stack, contents unspecified on return char *p = c; sprintf(p, "%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 p; } 

    由于c是在堆栈上分配的,因此当get_address_string返回时,内容未指定,再次导致未指定的行为。

    我更喜欢从调用者分配堆,以便明确谁应该释放它。

     #include  #include  bool GetString(char ** retString, size_t size) { // use size to do range check sprintf_s(*retString, size, "blah blah blah"); return true; } int _tmain(int argc, _TCHAR* argv[]) { size_t size = 100; char *data = (char *)malloc(size); if (data) { GetString(&data, size); free(data); } return 0; } 

      以上就是c/c++开发分享在C中返回字符串的正确方法相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注(猴子技术宅)。

      本文来自网络收集,不代表猴子技术宅立场,如涉及侵权请点击右边联系管理员删除。

      如若转载,请注明出处:https://www.ssfiction.com/c-cyuyankaifa/545860.html

      发表评论

      电子邮件地址不会被公开。 必填项已用*标注