Hey I am currently trying to switch from c++ to c and wonder if there is any way to avoid this because there are no more classes to use the implicit this->:
void func(Data *const longAndExpressiveName)
{
longAndExpressiveName->x += longAndExpressiveName->vel.x;
}
Because even if the name is not that long it still makes the code much harder to understand.
There is no syntax to accomplish your direct ask in C. The closest you can come is to create temporary variables.
int *xptr = &longAndExpressiveName->x;
int vel_x = longAndExpressiveName->vel.x;
*xptr += vel_x;
Your desire to use longAndExpressiveName is misplaced in this case, because in C++, you are coming from a syntax where longAndExpressiveName is not passed as a parameter, and the parameter is implicitly hidden by the implicit this->. The C++ syntax for the caller would be:
longAndExpressiveName->func();
And you are translating that into:
func(longAndExpressiveName);
And then you propagate that same name to the parameter name. While it may be appropriate for the caller to refer to the pointer with a long and expressive name, it is not really helpful to the "member" function. But, what would be helpful is if the function is named so that you know it is meant to do something to a particular kind of structure.
void func_Data(Data * const d) {
d->x += d->vel.x;
}
Which better captures the original C++ syntax:
void Data::func () {
x += vel.x;
}
C does not have any magic syntax to do what you want explicitly. However, you can just assign the parameter with a long and expressive name to a variable of the same or compatible type with a shorter name:
void func(Data *const longAndExpressiveName)
{
Data *const t = longAndExpressiveName;
t->x += t->vel.x;
}
This cuts down on typing if the long and expressive name would otherwise be repeated a lot in the function.
Related
I am coming from a C++ background, and have recently taken up C. I am am having trouble assigning a number to a type (or vice versa); what I need is some way to assign a unique ID to a type, preferably starting from 0. My goal is to have a function (or macro) that indexes an array based on a passed-in type, which I believe to only be achievable through macros.
Also, since I use the sizeof() the type which I need to be passed in, it makes using enums as an alternative difficult. If I were to pass the enumerator to the function/macro instead, then I would have to get the type from the number, the exact opposite (but maybe easier) problem.
Is this even possible in C? I have tried researching this question, but have not found any answer to this problem particularly, which I was able to do in C++ with templates, like so:
int curTypeIdx = 0;
template <typename T>
struct TypeHandle {
static int const val;
}
template <typename T>
int const TypeHandle<T>::val = curTypeIdx++;
The reason for this is that I am building an ECS. I have an EntityManager struct, which is supposed to contain arrays of components. Since I plan for this to be general-purpose, I defined an upper limit of components (MAX_COMPONENTS) and have an array of char*s of length MAX_COMPONENTS. At a basic level, The goal is to give the user of the EntityManager the ability to define their own components, and store them in these generic arrays.
If there is any other way to
Thank you all for any advice.
If you are OK with enumerating ALL supported types once( and update the list if language comes up with new types), then you can use the stringize functionality of C macros and an array of strings to achieve what you want.
#define GET_TYPE_ID(type) get_type_id(#type)
const char *type_strings[] = { "char", "unsigned char", "short" /* so on.. */};
int get_type_id(const char* type_string) {
for( int i = 0; i < sizeof(type_strings)/sizeof(const char*); i++) {
if ( strcmp(type_string, type_strings[i]) == 0 ) return i;
}
// Should never reach here if you have taken care of all types and
// don't pass in illegal types.
}
Now you can get an integer ID for each type with GET_TYPE_ID(int), GET_TYPE_ID(char) and so on.
For example:
int f1() {
return 3;
}
void f2(int *num) {
*num = 3;
}
int n1, n2;
n1 = f1();
f2(&n2);
With f1, we can return a value and do "variable=f1()"
But the same can be done with a void function that updates the value of that variable given its address without having to do "variable=f1()".
So, does this mean that we can actually just use void functions for everything? Or is there something that a void function cannot do to replace another int function/(type) function?
The main problem with making everything a void function (which in some people's lexicon is called a "routine") is that you can't chain them easily:
f(g(x))
becomes, if you really want to chain it:
int gout;
f((g(x, &gout), gout))
Which is painful.
Yes you could use void return types for everything and rely exclusively on returning via modified parameters. In fact, you could avoid using functions entirely and put everything in your main method.
As with any other feature of the language, return values give you particular advantages, and its up to you to decide if you want them. Here are some advantages of return values off the top of my head:
Returned values can be assigned to const variables, which can make your code easier to reason about
Certain types of optimisation can be applied by the compiler for returned values (this is more applicable to C++ RVO but may also apply to C's structs; I'm not sure)
Code which uses returned values is often easier to read, especially when the functions are mathematical (e.g. imagine having to declare all the temporaries manually for a large mathematical operation using sin/cos/etc. if they required the output to be via parameters). Compare:
double x = A*sin(a) + B*cos(b);
with
double tmpA, tmpB;
sin(&tmpA, a);
cos(&tmpB, b);
double x = A * tmpA + B * tmpB;
or to use a similar structure as John Zwinck suggested in his answer:
double tmpA, tmpB;
double x = A * (sin(&tmpA, a), tmpA) + B * (cos(&tmpB, b), tmpB);
It is guaranteed that the value will be set no matter what happens inside the function, as this is enforced by the compiler (except some very special cases such as longjumps)
You do not need to worry about checking if the assigned value is used or not; you can return the value and if the requester doesn't need it, they can ignore it (compare this to needing NULL-checks everywhere in your alternative method)
Of course there are also disadvantages:
You only get a single return value, so if your function logically returns multiple types of data (and they can't logically be combined into a single struct), returning via parameters may be better
Large objects may introduce performance penalties due to the need to copy them (which is why RVO was introduced in C++, which makes this much less of an issue)
So, does this mean that we can actually just use void functions for everything?
Indeed. And as it turn out, doing so is a fairly common coding style. But rather than void, such styles usually state that the return value should always be reserved for error codes.
In practice, you usually won't be able to stick to such a style consistently. There are a some special cases where not using the return value becomes inconvenient.
For example when writing callback functions of the kind used by standard C generic functions bsearch or qsort. The expect a callback of the format
int compare (const void *p1, const void *p2);
where the function returns less than zero, more than zero or zero. Design-wise it is important to keep the parameters passed as read-only, you wouldn't want your generic search algorithm to suddenly start modifying the searched contents. So while there is no reason in theory why these kind of functions couldn't be of void return type too, in practice it would make the code uglier and harder to read.
Of course you could; but that does not make it a good idea.
It may not always be convenient or lead to easy to comprehended code. A function returning void cannot be used directly as an operand in an expression. For example while you could write:
if( f1() == 3 )
{
...
}
for f2() you would have to write:
f2( &answer ) ;
if( answer )
{
...
}
Another issue is one of access control - by passing a pointer to the function you are giving that function indirect access to the caller's data, which is fine so long as the function is well behaved and does not overrun. A pointer may refer to a single object or an array of objects - the function taking that pointer has to impose appropriate rules, so it is intrinsically less safe.
Mostly for fun, I've decided to write my own minimal test framework for my C code. I use a basic struct for the test information, create an array of test structs and then iterate over them to run all the tests. This amounts to a very small amount of work for a fairly elegant (imho) solution.
However, the one thing that is a little annoying is that I cannot figure out how to define functions as function pointers instead of defining the function and then creating a function pointer later.
I have the following (which works just fine):
typedef int (* test_p) (void);
struct test {
char * desc;
test_p func;
};
int
example_test (void) {
puts("This is a test");
return 0;
}
void
run_test (char * test_name, test_p test) {
printf("Testing %s\t\t\t[ PEND ]\r", test_name);
char * test_result = (test() ? "FAIL" : "PASS");
printf("Testing %s\t\t\t[ %s ]\n", test_name, test_result);
}
int
main (void) {
struct test test_list [] = {
{ "example test", (test_p )example_test }
};
for ( int i = 0; i < 1; i ++ ) {
run_test(test_list[i].desc, test_list[i].func);
}
return 0;
}
However, I am hoping I can remove the need for the casting in the struct and instead define the function as being a function pointer from the beginning. The following is an example of how I would like this to work (assuming many of the same things as above):
test_p
example_test = {
puts("This is a test");
return 0;
}
If I could do something like this, then in the struct, I could simply have the func field be example_test rather than (test_p )example_test. Is this (or something like it) possible? If not, is there a reason why not (If that reason is simply "because it wasn't added to the language", that's fine)?
A function pointer is one kind of thing and a function is another kind of thing so you can't really make the latter be the former. But if you use a function name where a function pointer is expected, that produces a pointer to the function, so you can just remove the unnecessary cast, as WhozCraig said in the first comment above. You write
If I could do something like this, then in the struct, I could simply have the func field be example_test rather than (test_p )example_test.
You can do that, with example_test defined just as it is in your current code ... did you try that?
You can also forward declare a function, like so:
typedef int test_func(void); // note no indirection
typedef test_func* test_p;
test_func example_test;
It would be nice if you could use that sort of syntax when you define the function, as in your attempted syntax, but there's simply no way to do that in C ... you have to explicitly provide the return type and parameter list.
Another detail is that, when you invoke the function pointed to by a function pointer, you don't have to dereference it ... that's why you were able to write
test()
instead of
(*test)()
although the latter also works. (In fact, because the deference is stripped, (********test)() also works ... but only do that if you're trying to win an obfuscation contest.)
What you are describing is a kind of meta-programming. Rather than writing code to explicitly solve the problem, you are concerned with a kind of syntactic structure that will allow you to define a whole raft of test functions without unnecessary cruft.
In Lisp you would use macros. In C++ you might use templates and/or lambdas. In C you use macros.
So you need to write a macro that:
takes a name and descriptive text as arguments
defines a static variable of type function (created from that name using token pasting)
defines a function (using a name created by token pasting)
[edit] At this point you have achieved the goal: you have created the function and given it a name that is (only) a function pointer, and you can use that name in your struct without a cast. I would suggest one additional step, the macro also:
adds the variable/function and descriptive text to a list of functions to be tested.
Then your boilerplate loop iterates over the structure calling each function and reporting the results using the descriptive text. Problem solved.
Some people don't like macros, but they are ideally suited to this situation, and there is no other way to do it in C. I did something just like this before making the move to C++.
I am implementing simple library for lists in C, and I have a problem with writing find function.
I would like my function to accept any type of argument to find, both:
find(my_list, 3) and find(my_list, my_int_var_to_find).
I already have information what is type of list's elements.
For now I've found couple of ways dealing with this:
different function with suffix for different types: int findi(void* list, int i), int findd(void* list, double d) - but I don't like this approach, it seems like redundancy for me and an API is confusing.
using union:
typedef union {
int i;
double d;
char c;
...
} any_type;
but this way I force user to both know about any_type union, and to create it before invocation of find. I would like to avoid that.
using variadic function: int find(void* list, ...). I like this approach. However, I am concerned about no restrictions on number of arguments. User is free to write int x = find(list, 1, 2.0, 'c') although I don't know what it should mean.
I have seen also answer to this question: C : send different structures for one function argument but it's irrelevant, because I want to accept non-pointer arguments.
What is the proper way of handling this function?
You could instead try implementing your function similar to a generic function like bsearch, which can perform a binary search on an array of any data type:
void *bsearch(const void *key, const void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *))
Rather than hard-coding the different implementations for different data types inside your function, you instead pass a pointer to a function which will do the type-dependent operation, and only it knows the underlying implementation. In your case, that could be some sort of traversal/iteration function.
The other thing bsearch needs to know (apart from the obvious - search key and array length) is the size of each element in the array, so that it can calculate the address of each element in the array and pass it to the comparison function.
If you had a finite list of types that were to be operated on, there's nothing wrong with having a family of findX() functions. The above method requires a function for each data type to be passed to the bsearch function, however one of the main differences is that common functionality doesn't need to be repeated and the generic function can be used for any data type.
I wouldn't really say there's any proper way to do this, it's up to you and really depends on the problem you're trying to solve.
I am not sure whether answering my own question is polite, but I want your opinion.
I tried to solve this problem using va_list. Why so? Because this way I can write only one function. Please, mind that I know what type the argument should be. This way I can do this:
int find(void* list, ...) {
any_type object = {0};
int i = -1;
va_list args;
va_start(args, list);
switch(type_of_elem(list)) {
case INT: object.i = va_arg(args, int); break;
...
}
/* now &object is pointer to memory ready for comparision
* f.eg. using memcmp */
return i;
}
The advantage of this solution is that I can wrap presented switch-case and reuse it with other functions.
After researching a little bit more on my concern regarding no limit on number of arguments I realized that printf lacks this limit either. You can write printf("%d", 1, 2, 3).
But I tweaked my solution with additional macro:
#define find_(list, object) find((list), (object))
Which produces error message at compile time, saying that find_ macro expects 2 arguments not 3.
What do you think about it? Do you think this is better solution than previously suggested?
Our static analysis tool complains about a "useless type qualifier on return type" when we have prototypes in header files such as:
const int foo();
We defined it this way because the function is returning a constant that will never change, thinking that the API seemed clearer with const in place.
I feel like this is similar to explicitly initializing global variables to zero for clarity, even though the C standard already states that all globals will be initialized to zero if not explicitly initialized. At the end of the day, it really doesn't matter. (But the static analysis tool doesn't complain about that.)
My question is, is there any reason that this could cause a problem? Should we ignore the errors generated by the tool, or should we placate the tool at the possible cost of a less clear and consistent API? (It returns other const char* constants that the tool doesn't have a problem with.)
It's usually better for your code to describe as accurately as possible what's going on. You're getting this warning because the const in const int foo(); is basically meaningless. The API only seems clearer if you don't know what the const keyword means. Don't overload meaning like that; static is bad enough as it is, and there's no reason to add the potential for more confusion.
const char * means something different than const int does, which is why your tool doesn't complain about it. The former is a pointer to a constant string, meaning any code calling the function returning that type shouldn't try to modify the contents of the string (it might be in ROM for example). In the latter case, the system has no way to enforce that you not make changes to the returned int, so the qualifier is meaningless. A closer parallel to the return types would be:
const int foo();
char * const foo2();
which will both cause your static analysis to give the warning - adding a const qualifier to a return value is a meaningless operation. It only makes sense when you have a a reference parameter (or return type), like your const char * example.
In fact, I just made a little test program, and GCC even explicitly warns about this problem:
test.c:6: warning: type qualifiers ignored on function return type
So it's not just your static analysis program that's complaining.
You can use a different technique to illustrate your intent without making the tools unhappy.
#define CONST_RETURN
CONST_RETURN int foo();
You don't have a problem with const char * because that's declaring a pointer to constant chars, not a constant pointer.
Ignoring the const for now, foo() returns a value. You can do
int x = foo();
and assign the value returned by foo() to the variable x, in much the same way you can do
int x = 42;
to assign the value 42 to variable x.
But you cannot change the 42 ... or the value returned by foo(). Saying that the value returned from foo() cannot be changed, by applying the const keyword to the type of foo() accomplishes nothing.
Values cannot be const (or restrict, or volatile). Only objects can have type qualifiers.
Contrast with
const char *foo();
In this case, foo() returns a pointer to an object. The object pointed to by the value returned can be qualified const.
The int is returned by copy. It may be a copy of a const, but when it is assigned to something else, that something by virtue of the fact that it was assignable, cannot by definition be a const.
The keyword const has specific semantics within the language, whereas here you are misusing it as essentially a comment. Rather than adding clarity, it rather suggests a misunderstanding of the language semantics.
const int foo() is very different from const char* foo(). const char* foo() returns an array (usually a string) whose content is not allowed to change. Think about the difference between:
const char* a = "Hello World";
and
const int b = 1;
a is still a variable and can be assigned to other strings that can't change whereas b is not a variable. So
const char* foo();
const char* a = "Hello World\n";
a = foo();
is allowed but
const int bar();
const int b = 0;
b = bar();
is not allowed, even with the const declaration of bar().
Yes. I would advise writing code "explicitly", because it makes it clear to anyone (including yourself) when reading the code what you meant. You are writing code for other programmers to read, not to please the whims of the compiler and static analysis tools!
(However, you do have to be careful that any such "unnecessary code" does not cause different code to be generated!)
Some examples of explicit coding improving readability/maintainability:
I place brackets around portions of arithmetic expressions to explicitly specify what I want to happen. This makes it clear to any reader what I meant, and saves me having to worry about (or make ay mistakes with) precedence rules:
int a = b + c * d / e + f; // Hard to read- need to know precedence
int a = b + ((c * d) / e) + f; // Easy to read- clear explicit calculations
In C++, if you override a virtual function, then in the derived class you can declare it without mentioning "virtual" at all. Anyone reading the code can't tell that it's a virtual function, which can be disastrously misleading! However you can safely use the virtual keyword: virtual int MyFunc() and this makes it clear to anyone reading your class header that this method is virtual. (This "C++ syntax bug" is fixed in C# by requiring the use of the "override" keyword in this case - more proof if anyone needed it that missing out the "unnecessary virtual" is a really bad idea)
These are both clear examples where adding "unnecessary" code will make the code more readable and less prone to bugs.