In Go they often do the whole (err, val) thing, in Rust they do similar (+ syntactic sugar).
I'm not sure if I should have this type of struct for each of my types:
typedef struct {
int status;
char *const *c_str_arr;
size_t size;
} StatusAndArrayCStrArray;
extern void cleanup_struct_cstr_array(StatusAndArrayCStrArray *status_and_array) {
if (status_and_array->c_str_arr != NULL) {
free((void *) status_and_array->c_str_arr);
status_and_array->size = 0;
}
}
static const StatusAndArrayCStrArray statusAndArrayCStrArrayNull = {
EXIT_FAILURE, NULL, 0
};
That seems to be a lot of wasted space. Maybe a union would be better? - I've also seen some perror stuff so maybe I'm meant to set an error code and return the value, and then first check if there is an error the perror-way else return the value?
Related: Error handling in C code
As I understand
c_str_arrkeeps the error message. It does not have to be a part of this structure. It does not have to reside in the RAM (if RAM is a concern - for example uC programming). Have a second array with error messages in .rodata.sizeprobably it is the length of the message string. If message string is the null character terminated C string you do not need at all. I do not see any need of the dynamic allocations here.Eventually you need only the status code, nothing else.
extern void cleanup_struct_cstr_arrayfunctions are extern by definition and you do not need theexternkeywordEDIT (OPs comment):
If the server will return the complete message with some payload you cant use pointers to that data, you need to embed the data into the message.
payload will be the data returned from the server. It can be error message or another data. It can also be nothing.
Eventually if both size know the size of the payload (as it is defined somehow depending on the status) you may not need the
payload_sizemember at all.