I have the following code:
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;
}
The code works fine. However, I know this is not the proper way to return a string in C. I am receiving the warning "c is used uninitialized in this function".
What is the proper way to write this function in C?
"Proper way to return a string in C" is not truly possible. In C, a string is a character array (up to and including the null character) and arrays, by themselves, cannot be returned from a function.
A function can return pointers. So the usual method of "return a string" it to:
Return a pointer. char *foo1(...)
like char *strdup()
Pass in a pointer to a character array and modify its contents. void foo2(char *,...)
like int sprintf(char *dest, const char *format, ...)
Combine 1 & 2 char *foo3(char *, ...)
like char *strcpy(char *dest, char *src)
Pass the address of a pointer and update that. foo4(char **ptr)
like ssize_t getline(char **lineptr, size_t *n, FILE *stream)
The key is that the memory associated with the pointer must be valid after the function is complete. Returning a pointer to a function's non-static memory is undefined behavior. Successful methods include having the calling code pass in the pointer, or the function providing it via memory allocation of pointer to some persistent value like a global variable or string constant.
What is the proper way to write this function in C?
Current design practice encourages functions like #2 & #3 above to also supply a size_t size
so the function knowns the limitations of the memory available.
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;
}
Another method would allocate memory (I favor the above though). This obliges the calling code to free()
the memory.
#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
is a pointer, but no memory is allocated. The return value is ok, that's how it can be done in C.
But you need to allocate memory.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With