0

I have an array that is stack allocated and used to hold error messages. In most cases i call a function that returns an error code and based on that code i know what to add to the array, so i use a simple array:

char buf[1024];

Now I have a function that can return an error code or can provide some "results." In this case the array that holds the results is allocated elsewhere and there is no reason to copy from one array to the other so i really want to use a pointer to an array and pass that around. This way, if the function returns without error, then buf is ready to be consumed. So something like this:

char _buf[1024];
char **buf = &_buf;

Obviously this won't work because the types are wrong. Casting to a char** compiles (FWIW, I'm using gcc -std=c99 -W -Wall -g -gdb) but will segfault when I try to use *buf.

char _buf[1024];
char **buf = (char**)&_buf;

The current solution that I have is using an intermediate variable but this just seems to do what I want in a round about way:

char _buf[1024];
char *tmp = _buf;
char **buf = &tmp;

So, my question is: Is there a more appropriate way to accomplish these three lines?

4
  • You're using char ** as a pointer to a char array, which is wrong. Use char * instead. Commented Apr 6, 2014 at 17:20
  • You may want to show some sample code that involves the function that provides the "results". It's hard to suggest solutions without seeing what you are trying to do in action. Commented Apr 6, 2014 at 17:23
  • Just so i understand this, you're trying to double-duty your output parameter, a pointer to char* to receive a dynamic allocation upon "success" that is later caller-responsible for free'ing , while utilizing said-same output parameter to host a caller-provided address of an error message buffer to populate in the event of "failure". Is that accurate? Commented Apr 6, 2014 at 17:26
  • Please refrain from casts where you don't know exactly what you are doing and can explain why the cast is neccessary for correct working. Never muzzle the compiler, instead ask it to speak up: Use -Wall -Wextra, and handle all warnings appropriately. Commented Apr 6, 2014 at 17:26

2 Answers 2

1

Assuming this means what I think it does:

Now I have a function that can return an error code or can provide some "results."

your function accepts the address of a char* that will be populated with some dynamic results on success, but hosts as-input the address of an error message buffer to populate in the event of failure, and the caller is responsible of discerning the appropriate action to take based on the result of the function (success means free the results later, failure means the caller-provided input buffer now has the error message.

If that is accurate, then this is likely what you're wanting:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


// some function that fails when param is less than zero
int some_action(int param, char **res)
{
    if (param < 0)
    {
        if (*res)
            sprintf(*res, "param = %d", param);
        return -1;
    }

    *res = strdup("success data here");
    return 0;
}


int main()
{
    int i=0;

    for (i=-2; i<2; ++i)
    {
        char errmsg[1024] = "";
        char *res = errmsg;

        if (some_action(i, &res) == 0)
        {
            printf("Success: %s\n", res);
            free(res);
        }
        else
        {   // error (no free needed)
            printf("Error: %s\n", res);
        }
    }

    return 0;
}

Output

Error: param = -2
Error: param = -1
Success: success data here
Success: success data here

Note: i don't particularly advise this approach as you're not really saving anything in the long run unless you're expecting a significant number of errors, which should be an exception rather than a norm. Furthermore, if you still consider doing this I would strongly advise you provide error buffer length data to your action function and utilize it to ensure safety against a possible buffer overflow. (I would have done it, but you gotta do something here).

Sign up to request clarification or add additional context in comments.

1 Comment

This is the closest to what i was trying to do, but i didn't explain my design well enough for you all to answer fully. The buffer in question is the payload to send through a socket to a client. I've changed it so the code is always sent, the buffer only needs to be sent in the case of a results type call that succeeds. The error messages can be rendered client side. What i was trying to avoid is the case when the results requested is the whole array and not some subset of the array. IN this can i want to pass the array pointer to send rather than the "results" pointer.
0

Ultimately _buf just stores a pointer to the first element in the array

So if you want to be able to store a pointer to the array you would just have a char*

Example:

char _buf[1024];
char* pointToBuf = _buf;

Which is also the same as

char _buf[1024];
char* pointToBuf = &_buf[0];

You can now use pointToBuf in the same way as _buf

pointToBuf[0] = 'c';

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.