If I have a bunch of error codes in my application header.h like:
enum errors {
ERROR_NONE,
ERROR_TOTO,
ERROR_TATA,
ERROR_TUTU,
ERROR_MAX,
};
Should I define the string associated with each code in the header like this:
static const char * const errors_strings[ERROR_MAX] = {
"ERROR_NONE",
"Something happened with toto",
"Tata is wrong",
"Pasta or pizza?",
};
or directly in the printing function:
void print_error(int error)
{
char* array[ERROR_MAX] = {
"ERROR_NONE",
"Something happened with toto",
"Tata is wrong",
"Pasta or pizza?"
};
printf("%s\n", errors_strings[error]);
}
Which is the better practice?
First of all, make the error enum a named type with typedef. Ideally we shouldn't mix int and enum types but treat enum as distinct types, even though the weak type system in C doesn't provide much help there. (However, check out How to create type safe enums? for some tips & tricks.)
As for if you should have the string table outside a function or inside one, it entirely depends on if one or several functions are using it. If only one function is using it, then it's a good idea to place the table inside it, to reduce its scope.
Also since the string array has size ERROR_MAX it cannot hold more initialized items than that, but nothing prevents it from having less. Therefore to guarantee integrity between the enum and the table, always do this:
static const char * const errors_strings[] = { ... }; // no size specified
_Static_assert(sizeof errors_strings / sizeof *errors_strings == ERROR_MAX,
"helpful error message here");
Related
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_arr keeps 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.
size probably 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_array functions are extern by definition and you do not need the extern keyword
EDIT (OPs comment):
So I'm planning a few thousand functions each returning either the
value or an error, from remote server.
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.
typedef struct {
int status;
size_t payload_size;
char payload[];
} StatusAndArrayCStrArray;
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_size member at all.
Just out of curiosity, I'm trying to understand how pointers to functions work in C.
In order to associate a function to a typedef, I've declared a pointer in it, and then I've stored the address of the desired function in there.
This is what I was able to achieve:
typedef struct
{
void (*get)(char*, int);
char string[10];
} password;
int main()
{
password userPassword;
userPassword.get = &hiddenStringInput;
userPassword.get(userPassword.string, 10);
return EXIT_SUCCESS;
}
While this does actually work perfectly, I'd like for "userPassword.get" to be a shortcut that when used calls the hiddenStringInput function and fills in the requested arguments (in this case, an array of characters and a integer).
Basically, since I'm always going to use userPassword.get in association with the arguments "userPassword.string" and "10", I'm trying to figure out a way to somehow store those parameters in the pointer that points to the hiddenString function. Is it even possible?
The way I see this usually done is by providing a "dispatch" function:
void get(password * pw) {
pw->get(pw->string, 10);
}
Then, after setting userPassword.get to your function, you call just:
get(userPassword);
Obviously this adds some boilerplate code when done for multiple functions. Allows to implement further funny "class like" things, though.
You can do this in Clang using the "Blocks" language extension. As commented, there have been attempts to standardize this (and it's not been received with hostility or anything), but they're moving slowly.
Translated to use Blocks, your example could look like this:
#include <stdlib.h>
#include <Block.h>
typedef void (^GetPw)(int); // notice how Block pointer types are used
typedef void (*GetPw_Impl)(char*, int); // the same way as function pointer types
typedef struct
{
GetPw get;
char string[10];
} password;
extern void hiddenStringInput(char*, int);
extern void setPw(char dst [static 10], char * src);
GetPw bindPw (GetPw_Impl get_impl, char * pw)
{
return Block_copy (^ (int key) {
get_impl (pw, key);
});
}
int main()
{
password userPassword;
setPw(userPassword.string, "secret");
userPassword.get = bindPw(hiddenStringInput, userPassword.string);
userPassword.get(10);
return EXIT_SUCCESS;
}
There are some subtleties to the way arrays are captured that might confuse this case; the example captures the password by normal pointer and assumes userPassword is responsible for ownership of it, separately from the block.
Since a block captures values, it needs to provide and release dynamic storage for the copies of the captured values that will be created when the block itself is copied out of the scope where it was created; this is done with the Block_copy and Block_release functions.
Block types (syntactically function pointers, but using ^ instead of *) are just pointers - there's no way to access the underlying block entity, just like basic C functions.
This is the Clang API - standardization would change this slightly, and will probably reduce the requirement for dynamic memory allocation to copy a block around (but the Clang API reflects how these are currently most commonly used).
So, I've just realized that I can write functions directly inside of structs
typedef struct
{
char string[10];
void get(void)
{
hiddenStringInput(string, 10);
return;
}
void set(const char* newPassword)
{
strcpy(string, newPassword);
return;
}
void show(void)
{
printf("%s", string);
return;
}
} password;
Now I can just call userPassword.get(), userPassword.show() and userPassword.set("something"), and what happens is exactly what the label says. Are there any reasons I shouldn't do this? This looks like it could come pretty handy.
EDIT: So this is only possible in C++. I didn't realize I'm using a C++ compiler and by attempting to do random stuff I came up with this solution. So this isn't really what I was looking for.
Let's say I'm making a C program which display information about a precious stone when the user enter the stone's name.
The stones names never change and there are less than 20 of them so reading them from a external file at runtime seems a bit overkill.
I also need to access those names from multiple files (let's say two).
What I usually do is I declare a global char * array like so:
char *g_rsc_names[] = {"linemate", "deraumere", "sibur", "mendiane", "phiras", "thystane"};
in the file I need to use those. This look pretty fine to me but this only allow me to access the names in the file where I declare this global array.
In that case, what is the best/cleanest way to store the stones names?
You can wrap your array with a function which returns the const char* to the appropriate stone name and put that declaration into your global header file you include in multiple files:
const char* get_stone_name(size_t id);
Inside a source file define the get_stone_name like:
const char* get_stone_name(size_t id) {
static const char* const names[] = {
"linemate", "deraumere", "sibur", "mendiane", "phiras", "thystane"
};
return (id < (sizeof(names) / sizeof(names[0])) ? names[id] : "");
}
Decaring names as static will guarantee that won't be initialized more than once, and as a side option you can prevent the user to index your array out of bounds.
Define an enum with symbolic names for each stone. You would then store the enum value in the file instead of the name.
You could then define a function which will return the associated string for the given enum.
enum stones {
STONE_LINEMATE,
STONE_DERAMERE,
...
};
const char *stone_name(int stone)
{
switch (stone) {
case STONE_LINEMATE:
return "linemate";
case STONE_DERAMERE:
return "deraumere";
...
default:
return "";
}
Put a public declaration of the stones' data type in a header file, say stones.h:
// This lets any file that includes stones.h know that you've defined
// a variable named g_rsc_names.
extern char const *const g_rsc_names[];
The variable is defined as an array containing some number of character (string) pointers that will never change that each point to characters (strings) that will never change. This is to prevent programmer errors later and gives some hints to your compiler for optimization.
Then, in another file, stones.c:
// Populate the array.
char const *const g_rsc_names[] = {
"linemate", "deraumere", "sibur", "mendiane", "phiras", "thystane"
};
Now, include stones.h wherever you want to reference the array. Make sure to compile the stones.c file and link it to your binary.
Please ignore the topic of the post as it may sound something else instead of what I am actually asking here.
I want to make a C function which should retrieve me a string value associated with a specific integer code whose signature will be something very simple like:
char *Get_Msg (int code, char *errorInfoTable[][2]);
So, I need the strings as well associated codes stored first and because I cannot take an array of multiple datatypes, I end up storing the codes also in terms of strings as:
char *errorInfo[][2] = {
/* Error Code Error Message
* ---------- ------------- */
{ "0", "No error" },
{ "93", "Error in processing" },
{ "-32700", "PARSE_ERROR" },
{ "-32600", "INVALID_REQUEST " },
};
Then I may just read this table in the function which in turn should return me the associated string. Firstly, is it a good way to define this table inside that function itself or as a global variable in the file. But what if I wish to store this functionality in a separate C file and call it from some other file. I see that if I declare the file as a global variable, I need to declare an extern for char *errorInfoTable[][2] in the main file and the function and then parse in the function. I want the code to calculate the number of rows in the parsed table itself. This does not seem to work if I try to calculate the number of rows withing the Get_Msg function as the function cannot see it from the formal parameter char *errorInfoTable[][2]. I can do this by mentioning the number of rows in the formal parameter or passing the number of rows as well in the function but I don't want to calculate the number of rows explicitly anywhere. I want to design it in such a way that the programmer will just add/delete the number of rows in the table and should not touch any dimensions anywhere else in the program.
Is there any other way you to store and retrieve strings from this table? or any other better ways for this functionality?
struct { int error_code; const char *message; } errorInfo[] = {
/* Error Code Error Message
* ---------- ------------- */
{ -32700, "PARSE_ERROR" },
{ -32600, "INVALID_REQUEST " },
{ 0, "No error" },
{ 93, "Error in processing" },
};
That should give you what you want. And keeping it sorted can even allow you to do logarithmic lookup.
I'd also keep the table static and inside Get_Msg.
If you need to store more data relating to the code, you would do something like this:
struct error_code_data {
int error_code;
const char *message;
/* More data */
};
struct error_code_data const * get_error_code_data(int error_code);
In C99 is there an easier way of check if a structure of function pointers is NULL, other than checking each individual pointer?
What I currently have is similar to the following:
typedef struct {
void* (*foo)(int a);
int (*bar)(int a, int b);
} funcs;
void *funcs_dll;
funcs_dll = dlopen("my_funcs_dll.so", RTLD_GLOBAL);
if (funcs_dll == NULL) {
THROW_ERROR;
}
funs.foo = dlsym(funcs_dll, "foo");
funcs.bar = dlsym(funcs_dll, "bar");
if (!funcs.foo || !funcs.bar) {
THROW_ERROR;
}
What I am looking to do is reduce the second if check, so that I do not need to check each individual function. Any suggestions would be helpful.
Not directly, no.
You can't use memcmp() to compare to some constant buffer, since there might be padding inside the structure which will have "random" values. If you can make sure that the size of the structure is exactly the sum of the function pointer fields, you can perhaps go that way.
You can also use a proxy, by i.e. declaring an initial uint32_t member that is a bitset representing which function pointer(s) are valid. Then you can check up to 32 (or 64 with uint64_t) proxy bits in parallel.
If you only want to do this once, my suggestion would be a data-driven approach. Define a table of function names to look for, and process that in a loop, exiting as soon as a dlsym() call fails.
Something like:
const struct {
const char *name;
size_t offset;
} functions[] = {
{ "foo", offsetof(funcs, foo) },
{ "bar", offsetof(funcs, bar) },
};
Data-driven code like this is very powerful, and often very fast.
Make wrapper function for dlsym which will set error flag, if return value is NULL.