free of malloc inside the function, how to do that? - c

I create the malloc inside str function and i want to free this malloc variable
#include <stdio.h>
char *str(void)
{
// create the malloc
char *string = malloc(2); // how to free it
*(string + 0) = 'J';
*(string + 1) = 'O';
// return the malloc
return string;
}
int main(void)
{
// print the function
printf("%s, str());
return 0;
}

free(string)
would free it. But to print it as a string you must have the \0 in the end.
Note: You should not free it inside the function if your plan is to return it at the end of the function call. Since that would potentially give rise to undefined behavior.
Correct way of doing things:
char *str(void)
{
// create the malloc
char *string = malloc(3); // how to free it
if(string){
*(string + 0) = 'J';
*(string + 1) = 'O';
*(string + 2) = '\0';
// return the malloc
}
return string;
}
int main(void)
{
// print the function
char *s = str();
if(s)
printf("%s", s);
free(s);
return 0;
}
Incorrect
If you do this, then it would be a memory leak:
int main(void)
{
// print the function
printf("%s", str());
return 0;
}
And if you do this, then you have undefined behavior when you try to print it out.
char *str(void)
{
// create the malloc
char *string = malloc(2); // how to free it
*(string + 0) = 'J';
*(string + 1) = 'O';
// return the malloc
free(string);
return string;
}
int main(void)
{
// print the function
printf("%s", str()); // undefined behavior. A dragon might appear.
return 0;
}

Usually it is better alternative to let the caller provide the buffer to print to; if printing actually was successful could be hinted to via a return value; a new function signature might then look like this:
#include <stdbool.h>
bool str(size_t length, char buffer[length])
{
if(length < 3)
{
// buffer is too short...
return false;
}
buffer[0] = 'J';
buffer[1] = 'O';
buffer[2] = 0; // terminating null character, which you ommitted!
}
Note that the length specifier in the array parameter is ignored (function parameters only!), the definition is equivalent to char buffer[] or char* buffer; still specifying the length can serve to tell a user what kind of parameter actually is expected (-> self documenting code); note, too, that this only applies for the outer-most dimenstion (in char[12][10] the 12 is ignored but not the 10, the parameter type is equivalent to char(*)[10] which is a pointer to an array of length 10).
A user then is free where to allocate the string, dynamically on heap or on stack:
int main(void)
{
char stack[3];
if(str(sizeof(stack), stack))
{
printf("%s", stack);
}
size_t len = 3;
char* heap = malloc(len);
if(!heap) // should always be checked!
{
// allocation failed!
return -1;
}
if(str(len, heap))
{
printf("%s", heap);
}
free(heap);
return 0;
}
If you still want to retain the original signature then you need the returned string twice, once to print it, once to free it – i.e. you need to store it in an intermediate variable to be able to do so:
int main(void)
{
char* s = str(); // store it in a variable!
printf("%s", s); // still need to append the null terminator for!!!
free(s); // now you can free it
return 0;
}
If you don't append the null terminator then you need to explicitly limit the number of characters to print to console:
printf("%.2s", s);
// ^^ (!)

Related

Why strcpy crashes? [duplicate]

is that even possible?
Let's say that I want to return an array of two characters
char arr[2];
arr[0] = 'c';
arr[1] = 'a';
from a function. What type do I even use for the function? Is my only choice to use pointers and void the function? So far I've tried having a char* function or a char[]. Apparently you can only have functions of char(*[]). The only reason I want to avoid using pointers is the fact that the function has to end when it encounters a "return something;" because the value of "something" is a character array (not a string!) that might change size depending on the values I pass into the function through the main function. Thanks to anyone who responds in advance.
You've got several options:
1) Allocate your array on the heap using malloc(), and return a pointer to it. You'll also need to keep track of the length yourself:
void give_me_some_chars(char **arr, size_t *arr_len)
{
/* This function knows the array will be of length 2 */
char *result = malloc(2);
if (result) {
result[0] = 'c';
result[1] = 'a';
}
/* Set output parameters */
*arr = result;
*arr_len = 2;
}
void test(void)
{
char *ar;
size_t ar_len;
int i;
give_me_some_chars(&ar, &ar_len);
if (ar) {
printf("Array:\n");
for (i=0; i<ar_len; i++) {
printf(" [%d] = %c\n", i, ar[i]);
}
free(ar);
}
}
2) Allocate space for the array on the stack of the caller, and let the called function populate it:
#define ARRAY_LEN(x) (sizeof(x) / sizeof(x[0]))
/* Returns the number of items populated, or -1 if not enough space */
int give_me_some_chars(char *arr, int arr_len)
{
if (arr_len < 2)
return -1;
arr[0] = 'c';
arr[1] = 'a';
return 2;
}
void test(void)
{
char ar[2];
int num_items;
num_items = give_me_some_chars(ar, ARRAY_LEN(ar));
printf("Array:\n");
for (i=0; i<num_items; i++) {
printf(" [%d] = %c\n", i, ar[i]);
}
}
DO NOT TRY TO DO THIS
char* bad_bad_bad_bad(void)
{
char result[2]; /* This is allocated on the stack of this function
and is no longer valid after this function returns */
result[0] = 'c';
result[1] = 'a';
return result; /* BAD! */
}
void test(void)
{
char *arr = bad_bad_bad_bad();
/* arr is an invalid pointer! */
}
Since you have a predetermined size of you array you can in-fact return the array if you wrap it with a struct:
struct wrap
{
char a[2] ;
} ;
struct wrap Get( void )
{
struct wrap w = { 0 } ;
w.a[0] = 'c';
w.a[1] = 'a';
return w ;
}
You can return a pointer for the array from a function, however you can't return pointers to local arrays, the reference will be lost.
So you have 3 options:
Use a global variable:
char arr[2];
char * my_func(void){
arr[0] = 'c';
arr[1] = 'a';
return arr;
}
Use dynamic allocation (the caller will have the responsibility to free the pointer after using it; make that clear in your documentation)
char * my_func(void){
char *arr;
arr = malloc(2);
arr[0] = 'c';
arr[1] = 'a';
return arr;
}
Make the caller allocate the array and use it as a reference (my recommendation)
void my_func(char * arr){
arr[0] = 'c';
arr[1] = 'a';
}
If you really need the function to return the array, you can return the same reference as:
char * my_func(char * arr){
arr[0] = 'c';
arr[1] = 'a';
return arr;
}
You can pass the array to the function and let the function modify it, like this
void function(char *array)
{
array[0] = 'c';
array[1] = 'a';
}
and then
char array[2];
function(array);
printf("%c%c\n", array[0], array[1]);
If you want it as a return value, you should use dynamic memroy allocation,
char *function(void)
{
char *array;
array = malloc(2);
if (array == NULL)
return NULL;
array[0] = 'c';
array[1] = 'a';
return array;
}
then
char *array = function();
printf("%c%c\n", array[0], array[1]);
/* done using `array' so free it because you `malloc'ed it*/
free(array);
Important Note:
You should be aware of the fact that the array as filled above is not a string, so you can't for instance do this
printf("%s\n", array);
because the "%s" expects a matching string to be passed, and in c an array is not a string unless it's last character is '\0', so for a 2 character string you need to allocate space for 3 characters and set the last one to '\0'.
char* getCharArray()
{
return "ca";
}
This works perfecly:
int comm_read_data(int file_i2c, unsigned char** buffer)
{
*buffer = malloc(BUFFER_SIZE);
if (i2c_read_bytes(file_i2c, *buffer, BUFFER_SIZE) != 0)
{
return -1;
}
return BUFFER_SIZE;
}
And then call the function:
unsigned char* buffer;
int length = comm_read_data(file_i2c, &buffer);
/* parse the buffer here */
free(buffer);

string replace using dynamically allocated memory

I am using the below function to replace a sub-string in a given string
void ReplaceSubStr(char **inputString, const char *from, const char *to)
{
char *result = NULL;
int i, cnt = 0;
int tolen = strlen(to);
int fromlen = strlen(from);
if (*inputString == NULL)
return;
// Counting the number of times old word
// occur in the string
for (i = 0; (*inputString)[i] != '\0'; i++)
{
if (strstr((&(*inputString)[i]), from) == &(*inputString)[i])
{
cnt++;
// Jumping to index after the old word.
i += fromlen - 1;
}
}
// Making new string of enough length
result = (char *)malloc(i + cnt * (tolen - fromlen) + 1);
if (result == NULL)
return;
memset(result, 0, i + cnt * (tolen - fromlen) + 1);
i = 0;
while (&(*inputString))
{
// compare the substring with the result
if (strstr(*inputString, from) == *inputString)
{
strncpy(&result[i], to, strlen(to));
i += tolen;
*inputString += fromlen;
}
else
{
result[i++] = (*inputString)[0];
if ((*inputString)[1] == '\0')
break;
*inputString += 1;
}
}
result[i] = '\0';
*inputString = result;
return;
}
The problem with the above function is memory leak. Whatever memory is allocated for inputString will be lost after this line.
*inputString = result;
since I am using strstr and moving pointer of inputString *inputString += fromlen; inputString is pointing to NULL before the above line. So how to handle memory leak here.
Note: I dont want to return the new memory allocated inside the function. I need to alter the inputString memory based on new length.
You should use a local variable to iterate over the input string and avoid modifying *inputString before the final step where you free the previous string and replace it with the newly allocated pointer.
With the current API, ReplaceSubStr must be called with the address of a pointer to a block allocated with malloc() or similar. Passing a pointer to local storage or a string literal will have undefined behavior.
Here are a few ideas for improvement:
you could return the new string and leave it to the caller to free the previous one. In this case, you would take the input string by value instead of by address:
char *ReplaceSubStr(const char *inputString, const char *from, const char *to);
If the from string is empty, you should either insert the to string between each character of the input string or do nothing. As posted, your code has undefined behavior for this border case.
To check if the from string is present at offset i, use memcmp instead of strstr.
If cnt is 0, there is nothing to do.
You should return an error status for the caller to determine if memory could be allocated or not.
There is no need to initialize the result array.
avoid using strncpy(). This function has counter-intuitive semantics and is very often misused. Read this: https://randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/
Here is an improved version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int ReplaceSubStr(char **inputString, const char *from, const char *to) {
char *input = *inputString;
char *p, *q, *result;
size_t cnt;
size_t tolen = strlen(to);
size_t fromlen = strlen(from);
if (input == NULL || fromlen == 0)
return 0;
// Counting the number of times old word occurs in the string
for (cnt = 0, p = input; (p = strstr(p, from)) != NULL; cnt++) {
p += fromlen;
}
if (cnt == 0) // no occurrence, nothing to do.
return 0;
// Making new string of enough length
result = (char *)malloc(strlen(input) + cnt * (tolen - fromlen) + 1);
if (result == NULL)
return -1;
for (p = input, q = result;;) {
char *p0 = p;
p = strstr(p, from);
if (p == NULL) {
strcpy(q, p0);
break;
}
memcpy(q, p0, p - p0);
q += p - p0;
memcpy(q, to, tolen);
q += tolen;
p += fromlen;
}
free(*inputString);
*inputString = result;
return 0;
}
int main() {
char *p = strdup("Hello world!");
ReplaceSubStr(&p, "l", "");
printf("%s\n", p); // prints Heo word!
free(p);
return 0;
}
You cannot obviously free the input as it can be a literal, some memory you don't control. That would cripple your function even more than now.
You could return the old value of inputString so you'd be able to free it if needed.
char *ReplaceSubStr(char **inputString, const char *from, const char *to)
{
char *old_string = *inputString;
...
return old_string;
}
The caller is responsible to free the contents of old_string if needed.
If not needed (we have to workaround the char ** input by assigning a valid writable array to a pointer to be able to pass this pointer:
char input[]="hello world";
char *ptr = input;
ReplaceSubStr(&ptr, "hello", "hi");
// input is now "hi world" in a different location
free(ptr); // when replaced string isn't needed
if needed:
char *input = strdup("hello world");
char *old_input = ReplaceSubStr(&input, "hello", "hi");
free(old_input);
or just
free(ReplaceSubStr(&input, "hello", "hi"));
then always (when replaced string isn't needed):
free(input);
The only constraint is that you cannot use a constant string literal as input (const char *input = "hello world") because of the prototype & the possible return of a char * to pass to free.

Passing Character Array to Function and Return Character Array [duplicate]

is that even possible?
Let's say that I want to return an array of two characters
char arr[2];
arr[0] = 'c';
arr[1] = 'a';
from a function. What type do I even use for the function? Is my only choice to use pointers and void the function? So far I've tried having a char* function or a char[]. Apparently you can only have functions of char(*[]). The only reason I want to avoid using pointers is the fact that the function has to end when it encounters a "return something;" because the value of "something" is a character array (not a string!) that might change size depending on the values I pass into the function through the main function. Thanks to anyone who responds in advance.
You've got several options:
1) Allocate your array on the heap using malloc(), and return a pointer to it. You'll also need to keep track of the length yourself:
void give_me_some_chars(char **arr, size_t *arr_len)
{
/* This function knows the array will be of length 2 */
char *result = malloc(2);
if (result) {
result[0] = 'c';
result[1] = 'a';
}
/* Set output parameters */
*arr = result;
*arr_len = 2;
}
void test(void)
{
char *ar;
size_t ar_len;
int i;
give_me_some_chars(&ar, &ar_len);
if (ar) {
printf("Array:\n");
for (i=0; i<ar_len; i++) {
printf(" [%d] = %c\n", i, ar[i]);
}
free(ar);
}
}
2) Allocate space for the array on the stack of the caller, and let the called function populate it:
#define ARRAY_LEN(x) (sizeof(x) / sizeof(x[0]))
/* Returns the number of items populated, or -1 if not enough space */
int give_me_some_chars(char *arr, int arr_len)
{
if (arr_len < 2)
return -1;
arr[0] = 'c';
arr[1] = 'a';
return 2;
}
void test(void)
{
char ar[2];
int num_items;
num_items = give_me_some_chars(ar, ARRAY_LEN(ar));
printf("Array:\n");
for (i=0; i<num_items; i++) {
printf(" [%d] = %c\n", i, ar[i]);
}
}
DO NOT TRY TO DO THIS
char* bad_bad_bad_bad(void)
{
char result[2]; /* This is allocated on the stack of this function
and is no longer valid after this function returns */
result[0] = 'c';
result[1] = 'a';
return result; /* BAD! */
}
void test(void)
{
char *arr = bad_bad_bad_bad();
/* arr is an invalid pointer! */
}
Since you have a predetermined size of you array you can in-fact return the array if you wrap it with a struct:
struct wrap
{
char a[2] ;
} ;
struct wrap Get( void )
{
struct wrap w = { 0 } ;
w.a[0] = 'c';
w.a[1] = 'a';
return w ;
}
You can return a pointer for the array from a function, however you can't return pointers to local arrays, the reference will be lost.
So you have 3 options:
Use a global variable:
char arr[2];
char * my_func(void){
arr[0] = 'c';
arr[1] = 'a';
return arr;
}
Use dynamic allocation (the caller will have the responsibility to free the pointer after using it; make that clear in your documentation)
char * my_func(void){
char *arr;
arr = malloc(2);
arr[0] = 'c';
arr[1] = 'a';
return arr;
}
Make the caller allocate the array and use it as a reference (my recommendation)
void my_func(char * arr){
arr[0] = 'c';
arr[1] = 'a';
}
If you really need the function to return the array, you can return the same reference as:
char * my_func(char * arr){
arr[0] = 'c';
arr[1] = 'a';
return arr;
}
You can pass the array to the function and let the function modify it, like this
void function(char *array)
{
array[0] = 'c';
array[1] = 'a';
}
and then
char array[2];
function(array);
printf("%c%c\n", array[0], array[1]);
If you want it as a return value, you should use dynamic memroy allocation,
char *function(void)
{
char *array;
array = malloc(2);
if (array == NULL)
return NULL;
array[0] = 'c';
array[1] = 'a';
return array;
}
then
char *array = function();
printf("%c%c\n", array[0], array[1]);
/* done using `array' so free it because you `malloc'ed it*/
free(array);
Important Note:
You should be aware of the fact that the array as filled above is not a string, so you can't for instance do this
printf("%s\n", array);
because the "%s" expects a matching string to be passed, and in c an array is not a string unless it's last character is '\0', so for a 2 character string you need to allocate space for 3 characters and set the last one to '\0'.
char* getCharArray()
{
return "ca";
}
This works perfecly:
int comm_read_data(int file_i2c, unsigned char** buffer)
{
*buffer = malloc(BUFFER_SIZE);
if (i2c_read_bytes(file_i2c, *buffer, BUFFER_SIZE) != 0)
{
return -1;
}
return BUFFER_SIZE;
}
And then call the function:
unsigned char* buffer;
int length = comm_read_data(file_i2c, &buffer);
/* parse the buffer here */
free(buffer);

Custom concat function in C with pointer

I try to code my own concatenation function in C without library, but I have issue and I don't know where it comes from.
To do my function I use pointers of char.
This is my Code :
#include <stdio.h>
#include <stdlib.h>
int longueur(char *str)
{
int i =0;
while(str[i] != '\0')
{
i++;
}
return i;
}
void concat(char* source, char* dest)
{
int longStr1 = (longueur(source));
int longStr2 = (longueur(dest));
int i=0, j=0;
char* temp = dest;
free(dest);
dest = (char*) realloc(dest, ((longStr1 + longStr2)* sizeof(char)));
/*dest[0] = temp[0]; <------ If I do this it will generate issue, so the bellow code too*/
while(temp[i] != '\0')
{
dest[i] = temp[i];
i++;
}
while(source[j] != '\0')
{
dest[i] = source[j];
i++;
j++;
}
dest[i] = '\0';
}
int main()
{
char *str1 = "World";
char *str2 = "Hello";
concat(str1, str2);
printf("-------------\n%s", str2);
return 0;
}
EDIT
I read all your answer, so I changed my concat function to :
void concat(char* source, char* dest)
{
int longStr1 = (longueur(source));
int longStr2 = (longueur(dest));
int i=0, j=0;
dest = (char*) malloc((longStr1 + longStr2)* sizeof(char) + sizeof(char));
while(dest[i] != '\0')
{
dest[i] = dest[i];
i++;
}
while(source[j] != '\0')
{
dest[i] = source[j];
i++;
j++;
}
dest[i] = '\0';
}
Now I don't have issue but my code only display "Hello"
In addition to all the good comments and solutions: realloc can give you a different pointer and you must return that pointer. So your function signature should be:
void concat(char* source, char** dest)
{
int longStr1 = (longueur(source));
int longStr2 = (longueur(dest));
int i=0, j=0;
char* temp = *dest, *temp2;
if ((temp2 = realloc(dest, ((longStr1 + longStr2)+1))==NULL) return;
*dest= temp2;
while(temp[i] != '\0')
{
*dest[i] = temp[i];
i++;
}
while(source[j] != '\0')
{
*dest[i] = source[j];
i++;
j++;
}
*dest[i] = '\0';
}
..and this assumes the function will only be called with a dest that was allocated with malloc. And sizeof(char) is always 1. (This resulting function is not optimal.)
--EDIT--
Below the correct, optimized version:
void concat(char* source, char** dest)
{
int longSrc = longueur(source);
int longDst = longueur(dest);
char *pDst, *pSrc;
if ((pDst = realloc(*dest, longSrc + longDst + 1))==NULL) return;
if (pDst != *dest) *dest= pDst;
pDst += longSrc;
pSrc= source;
while(pSrc)
*pDst++ = *pSrc++;
*pDst = '\0';
}
In your code
free(dest);
and
dest = (char*) realloc(dest, ((longStr1 + longStr2)* sizeof(char)));
invokes undefined behavior as none of them use a pointer previously allocated by malloc() or family.
Mostly aligned with your approach, you need to make use of another pointer, allocate dynamic memory and return that pointer. Do not try to alter the pointers received as parameters as you've passed string literals.
That said, you need to have some basic concepts clear first.
You need not free() a memory unless it is allocated through malloc() family.
You need to have a char extra allocated to hold the terminating null.
Please see this discussion on why not to cast the return value of malloc() and family in C..
If your concatenation function allocates memory, then, the caller needs to take care of free()-ing the memory, otherwise it will result in memory leak.
After you have freed dest here:
free(dest);
You cannot use this pointer in following call to realloc:
dest = (char*) realloc(dest, ((longStr1 + longStr2)* sizeof(char)));
/*dest[0] = temp[0]; <------ If I do this it will generate issue, so the bellow code too*/
man realloc
void *realloc(void *ptr, size_t size);
The realloc() function changes the size of the memory block
pointed to by ptr to size bytes. (...)
But this pointer is invalid now and you cannot use it anymore. When you call free(dest), the memory dest points to is being freed, but the value of dest stays untouched, making the dest a dangling pointer. Accessing the memory that has already been freed produces undefined behavior.
NOTE:
Even if free(dest) is technically valid when called on pointer to memory allocated by malloc (it is not an error in your function to call free(dest) then), it is incorrect to use this on pointer to literal string as you do in your example (because str2 points to string literal it is an error to pass this pointer to function calling free on it).
Given your original use, perhaps you would find a variant like this useful
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
size_t longueur ( const char * str ) { /* correct type for string lengths */
size_t len = 0;
while (*str++ != '\0') ++len;
return len;
}
char * concat ( const char * first, const char * second ) {
const char * s1 = first ? first : ""; /* allow NULL input(s) to be */
const char * s2 = second ? second : ""; /* treated as empty strings */
size_t ls1 = longueur(s1);
size_t ls2 = longueur(s2);
char * result = malloc( ls1 + ls2 + 1 ); /* +1 for NUL at the end */
char * dst = result;
if (dst != NULL) {
while ((*dst = *s1++) != '\0') ++dst; /* copy s1\0 */
while ((*dst = *s2++) != '\0') ++dst; /* copy s2\0 starting on s1's \0 */
}
return result;
}
int main ( void ) {
const char *str1 = "Hello";
const char *str2 = " World";
char * greeting = concat(str1, str2);
printf("-------------\n%s\n-------------\n", greeting);
free(greeting);
return 0;
}
In this variant, the two inputs are concatenated and the result of the concatenation is returned. The two inputs are left untouched.

How can I return a character array from a function in C?

is that even possible?
Let's say that I want to return an array of two characters
char arr[2];
arr[0] = 'c';
arr[1] = 'a';
from a function. What type do I even use for the function? Is my only choice to use pointers and void the function? So far I've tried having a char* function or a char[]. Apparently you can only have functions of char(*[]). The only reason I want to avoid using pointers is the fact that the function has to end when it encounters a "return something;" because the value of "something" is a character array (not a string!) that might change size depending on the values I pass into the function through the main function. Thanks to anyone who responds in advance.
You've got several options:
1) Allocate your array on the heap using malloc(), and return a pointer to it. You'll also need to keep track of the length yourself:
void give_me_some_chars(char **arr, size_t *arr_len)
{
/* This function knows the array will be of length 2 */
char *result = malloc(2);
if (result) {
result[0] = 'c';
result[1] = 'a';
}
/* Set output parameters */
*arr = result;
*arr_len = 2;
}
void test(void)
{
char *ar;
size_t ar_len;
int i;
give_me_some_chars(&ar, &ar_len);
if (ar) {
printf("Array:\n");
for (i=0; i<ar_len; i++) {
printf(" [%d] = %c\n", i, ar[i]);
}
free(ar);
}
}
2) Allocate space for the array on the stack of the caller, and let the called function populate it:
#define ARRAY_LEN(x) (sizeof(x) / sizeof(x[0]))
/* Returns the number of items populated, or -1 if not enough space */
int give_me_some_chars(char *arr, int arr_len)
{
if (arr_len < 2)
return -1;
arr[0] = 'c';
arr[1] = 'a';
return 2;
}
void test(void)
{
char ar[2];
int num_items;
num_items = give_me_some_chars(ar, ARRAY_LEN(ar));
printf("Array:\n");
for (i=0; i<num_items; i++) {
printf(" [%d] = %c\n", i, ar[i]);
}
}
DO NOT TRY TO DO THIS
char* bad_bad_bad_bad(void)
{
char result[2]; /* This is allocated on the stack of this function
and is no longer valid after this function returns */
result[0] = 'c';
result[1] = 'a';
return result; /* BAD! */
}
void test(void)
{
char *arr = bad_bad_bad_bad();
/* arr is an invalid pointer! */
}
Since you have a predetermined size of you array you can in-fact return the array if you wrap it with a struct:
struct wrap
{
char a[2] ;
} ;
struct wrap Get( void )
{
struct wrap w = { 0 } ;
w.a[0] = 'c';
w.a[1] = 'a';
return w ;
}
You can return a pointer for the array from a function, however you can't return pointers to local arrays, the reference will be lost.
So you have 3 options:
Use a global variable:
char arr[2];
char * my_func(void){
arr[0] = 'c';
arr[1] = 'a';
return arr;
}
Use dynamic allocation (the caller will have the responsibility to free the pointer after using it; make that clear in your documentation)
char * my_func(void){
char *arr;
arr = malloc(2);
arr[0] = 'c';
arr[1] = 'a';
return arr;
}
Make the caller allocate the array and use it as a reference (my recommendation)
void my_func(char * arr){
arr[0] = 'c';
arr[1] = 'a';
}
If you really need the function to return the array, you can return the same reference as:
char * my_func(char * arr){
arr[0] = 'c';
arr[1] = 'a';
return arr;
}
You can pass the array to the function and let the function modify it, like this
void function(char *array)
{
array[0] = 'c';
array[1] = 'a';
}
and then
char array[2];
function(array);
printf("%c%c\n", array[0], array[1]);
If you want it as a return value, you should use dynamic memroy allocation,
char *function(void)
{
char *array;
array = malloc(2);
if (array == NULL)
return NULL;
array[0] = 'c';
array[1] = 'a';
return array;
}
then
char *array = function();
printf("%c%c\n", array[0], array[1]);
/* done using `array' so free it because you `malloc'ed it*/
free(array);
Important Note:
You should be aware of the fact that the array as filled above is not a string, so you can't for instance do this
printf("%s\n", array);
because the "%s" expects a matching string to be passed, and in c an array is not a string unless it's last character is '\0', so for a 2 character string you need to allocate space for 3 characters and set the last one to '\0'.
char* getCharArray()
{
return "ca";
}
This works perfecly:
int comm_read_data(int file_i2c, unsigned char** buffer)
{
*buffer = malloc(BUFFER_SIZE);
if (i2c_read_bytes(file_i2c, *buffer, BUFFER_SIZE) != 0)
{
return -1;
}
return BUFFER_SIZE;
}
And then call the function:
unsigned char* buffer;
int length = comm_read_data(file_i2c, &buffer);
/* parse the buffer here */
free(buffer);

Resources