0

I am writing a program for ESP8266 on Arduino SDK. My C knowledge is not enough to create professional project so I am training my self about C programming concepts now.

I deep dive to pointers and I tried write a function that return one float value and one string value. I used pointers to do that. For float, everything went well but I cannot return string value.

Here is the my code:

float val1;
char val2;

void returnMultiple(float *fGross, char *sGross)
{
  *fGross = 50.0;
  char v_str[10];
  dtostrf(*fGross, 5, 2, v_str);
  sprintf(v_str, "%s", v_str);
  sGross = v_str;
}

What is the point that I missed? My char value null or esp8266 restarting?

5
  • You assign to sGross pointer the value of local variable v_str... but that data will be destroyed as soon as the function returns (it is stored in the stack, so it will be overwritten) Commented Jan 7, 2020 at 9:26
  • 3
    Does this answer your question? malloc vs array in C Commented Jan 7, 2020 at 9:28
  • So how can i fix it? My aim is, convert float to char array then assign it to a pointer to use this on another parts of the program. Commented Jan 7, 2020 at 9:30
  • You can replace char v_str[10]; with char *v_str = malloc(10 * sizeof(char)); Commented Jan 7, 2020 at 9:31
  • How do you call this function? You could provide the buffer for conversion in the caller function and within your function you could put the string directly into that buffer. Commented Jan 7, 2020 at 9:32

4 Answers 4

0

An option is to directly copy into the sGross.

dtostrf(*fGross, 5, 2, sGross);

Then you have to be sure the function calling has allocated enough memory.

void main()
{
    float val1;
    char val2[10];

    returnMultiple(&val1, val2);
}

The end result will then be

void returnMultiple(float *fGross, char *sGross)
{
    *fGross = 50.0;
    dtostrf(*fGross, 5, 2, sGross);
}
Sign up to request clarification or add additional context in comments.

Comments

0

If you define an interface you do not only need to specify the function signature but also how to call it. Typical questions are:

  • What type of memory is used for buffers
  • Who will allocate the memory
  • Who will free the memory

If you define that the caller has to provide the buffer, your code could look like this:

void returnMultiple(float *fGross, char *sGross)
{
  if (fGross == NULL || sGross == NULL)
    return;

  *fGross = 50.0;
  dtostrf(*fGross, 5, 2, sGross);
}

void callerfunc(void)
{
    char buf[10];
    float flt;
    returnMultiple(&flt, buf);
    printf("flt: %f; str: %s\n", flt, buf);
}

As no dynamic memory allocation is done, nothing needs to be freed. You might define another return type to allow for error indications.

1 Comment

I tried it and i got this method. Thanks for the help!.
0

You assign to sGross pointer the value of local variable v_str... but that data will be destroyed as soon as the function returns (it is stored in the stack, so it will be overwritten).

What you need to do is to allocate the buffer externally. You can either

  • Use dynamic memory with something like char *str = malloc(10 * sizeof(char)); (remembering to free it as soon as it is no more needed).
  • Define externally an array of chars, like in the example below
float val1;
char val2;

void returnMultiple(float *fGross, char *sGross)
{
  *fGross = 50.0;
  char v_str[10];
  dtostrf(*fGross, 5, 2, v_str);

  /* CHANGES HERE! */
  sprintf(sGross, "%s", v_str);
  // No need to assign to sGross the pointer of a local variable 
  // sGross = v_str;
}

int main( void )
{
  char testString[10];
  float testFloat;

  returnMultiple(&testFloat, testString);

  printf("%s\n", testString);

  return 0;
}

In this case I would suggest to pass not only the char pointer, but also the size of the buffer.

Another solution is allocating the char array within returnMultiple() function, returning the pointer to the char array. sGross parameter in this case would become a char ** variable.

But I suggest starting with easier solutions like the one showed in my example.

Comments

0

First: Your problem is with the way you return the string, not the float, so I'm reducing my example to just returning the string.

There are two ways you can implement this: Either the memory for your string is allocated by the function, or by the caller. The easy way is this:

void toString(char *str, int d) {
    sprinf(str, "%d", d);
}

int main(void) {
    char result[12];
    toString(result, 50);
    puts(result, stdout);
    return 0;
}

In this case, result is a 12 byte string allocated on the stack of main. 12 bytes is big enough to store the string representation of an integer, so that's safe, if you're not sure what size the result can have, then watch out.

Second option:

void toString(char **str, int d) {
    char *v_str = malloc(12);
    sprintf(v_str, "%d", d);
    *str = v_str;
}

int main(void) {
    char *result;
    toString(&result, 50);
    puts(result, stdout);
    free(result);
    return 0;
}

In this case, we pretend that the caller doesn't know how much memory is required for the result string, and let the toString function decide. It allocates as much memory as it needs for the conversion, then returns the allocated string. The caller needs to release that memory with free. Note that we've got to pass the address &result in this situation, so toString will write the pointer to the allocated string into our result variable. Double pointers like this can seem confusing to some people who are new to C, but it's conceptually similar to how you're passing a pointer to your float variable (float *fGross).

Personally, I prefer the first version when possible, because allocating memory on the stack avoids having to manage heap memory with malloc and free, a common source of memory leaks, especially for beginners. Of course, nothing prevents you from calling that version of toString with heap-allocated memory if you need to.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.