Casting void* to other types - c

I'm getting the error:
error: 'void*' is not a pointer-to-object type
For the following code:
Button config_b1 = Button("b1");
Button config_b2 = Button("b2");
Button config_b3 = Button("b3");
const void *const buttons[3] PROGMEM = {
&config_b1, &config_b2, &config_b3
};
in some function:
(Button)*buttons[1]->setText("Foo");
The casting to Button fails.
This is just a simplified example. The array "buttons" will have different types of objects, so I need to initialize it as void and then cast to the proper type inside the function.

I think this is a simple precedence error, and you need
((Button *) buttons[1])->setText("foo");
Are you sure this is C, by the way? That kind of call really looks like C++ (it could be C, but then you'd need an explicit this equivalent in most cases).

Related

How to assign base address for a function pointer returning enum?

I have a function pointer which returns an enum
My enum is
typedef enum {
FIRST,
SECOND,
THIRD
} STATUS;
In the code some one has tried to assign a base address as
STATUS (*start_port)(void *,void *)= 0x80000001;
But it is throwing the warnings
"initialization makes pointer from integer without a cast"
and also
"ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]"
I put the declaration separate
STATUS (*start_port)(void *,void *);
Then tried to assign the address to the function pointer in the following way
start_port = (unsigned int *)0x80000001;
it corrected the mixed declaration warning but a new error came up
"assignment from incompatible pointer type"
I would like to know how to properly type caste a function pointer to a fixed (constant) base address when the return value is an enum.
As have been stated in other answers, you have to use explicit cast to convert integer into function pointer:
STATUS (*start_port)(void *,void *)= (STATUS(*)(void *,void *))0x80000001;
But function pointers are hard to read. Use typedef to make them more clean:
typedef STATUS FuncType(void*, void*);
...
FuncType * start_port = (FuncType *)0x80000001;
You are declaring start_port of type function pointer and then try to assign a unsigned int * pointer to it, try
STATUS (*start_port)(void *,void *) = (STATUS (*)(void *,void *)) 0x80000001;
but this is terrible style and you should not do it.
It's a warning telling you not to declare variables inside the code, it's something that is no longer a problem with modern versions of the c standard but IMHO is still a good practice. Delcaring variables within the code makes it harder to follow the algorithm and the logic. Whereas declaring them only at the beginning of a block makes it easier to read the code as a whole. You know where the declarations are and you don't need to skip over parts of the code that are just "declarations".
The same problem as (1), so the right way to cast is
start_port = (STATUS (*)(void *,void *)) 0x80000001;

What is the correct way of casting const char* to char* without changing the API and not getting a warning

In my plain C99 project, I have an external C library that defines an interface (via GObject interfaces) that I need to implement:
void interface_function (const char *address, [...]);
Now, within the implementation (that I need to write) I need to call some other functions from a different library (so I can't change them) to which I need to pass *address, but their method signature omit the const keyword:
void some_api_function (char *address, [...]);
Now, if I simply pass *address down to some_api_function, I will get the compiler warning:
warning: passing argument 1 of ‘some_api_function’ discards ‘const’ qualifier from pointer target type [enabled by default]
I tried explicitly casting to char * in the function call like this:
`some_api_function ((char*) address, [...]) { ... }
but then I just get another warning:
warning: cast discards ‘__attribute__((const))’ qualifier from pointer target type [-Wcast-qual]
The problem is, that this is a larger C project with many people working on and policy is that -Werror is enabled and no code emitting warnings on compile is accepted into the mainline source code.
I can't change the interface definition because it is from a third party, and I can't change the API definitions of the external libraries, either. I know that *address is not modified in the external library (it could be const, but as I said I can't change that)
I also know that to solve this issue, I could just create a copy of the const char* into char *, but that doesn't feel right to me because it involves a unnecessary copy operation .
So what is the elegant or 'right' way to do this?
For absolute safety I'd deep copy the string and profile the performance impact. The author of the function makes no guarantee that they will not modify the string. If a parameter is marked const char* there is an implication that the string will not be changed by the function.
There are other choices; casting via (void*) or a clever union trick (see Gung Foo's answer), but neither will guarantee program stability.
You could use a union.
union charunion {
char *chr;
const char* cchr;
} chrptrs;
chrptrs.cchr; // const char *
chrptrs.chr; // char *
Warnings are there for a reason. As Bathseheeba says, the declaration makes no guarantee that the function will not modify the value, so if you know what you are doing -i.e. you know the function will not try to modify the value pointed by 'address'-, you can remove the warning by doing this:
void interface_function (const char *address, [...])
{
char *chrptr=(char *)address;
[...]
some_api_function (chrptr, [...]);
[...]
}
EDIT: I was answering before you commented that you were going with Bathsheeba's suggestion. Good choice.

Undefined behavior when passing a pointer to a function with a formal parameter of pointer to const?

I have been working on some code that is similar to the following:
typedef struct
{
unsigned char x;
unsigned short y;
unsigned char[NUM_DEFINED_ELSEWHERE];
} My_Struct;
static My_Struct my_useful_struct; // Variables initialized elsewhere in code.
void myFunction(const My_Struct * p_my_struct)
{
/* Performs various read-only actions utilizing p_my_struct. */
}
void myOtherFunction(void)
{
static My_Struct * p_struct = &my_useful_struct;
myFunction(p_struct);
}
My code compiles without any problems, but when reviewed I was told that unless I typecast p_struct that this could lead to undefined behavior on certain platforms (i.e. 8051). However, I never even received a warning on the compiler. Is it true that not typecasting the pointer when passing it to the function with (const My_Struct *) could lead to undefined behavior?
The reason that I declared the above function with a pointer to const was because I wanted to be able to handle both a pointer to const and a pointer. Is it bad coding practice not to typecast in the above situation?
Thanks for your help!
This is absolutely fine; the compiler performs an implicit conversion from My_Struct * to const My_Struct *. §6.3.2.3 of the C99 spec says:
For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type; the values stored in the original and converted pointers shall compare equal.
Furthermore, even if you declare the function with two inconsistent declarations, such that one file sees it declared like this:
void myFunction(My_Struct * p_my_struct);
even though it's actually defined like this:
void myFunction(const My_Struct * p_my_struct) { ... }
even that is allowed by the spec, even though the compiler doesn't know to perform an implicit conversion, because My_Struct * and const My_Struct * have the same representation (so the conversion is a no-op, anyway).
(Thanks to Christoph and awoodland for their comments clarifying the latter situation. In a previous version of this answer, I wrongly claimed that that would be undefined behavior.)
Edited to add: The reverse — defining a function with a declaration with a pointer-to-non-const parameter, but calling it using a declaration with a pointer-to-const parameter — is also allowed, for the same reason; but attempting to actually modify the data could well result in undefined behavior, depending on where it's from. (A char * can by initialized a string constant, for example, but it's undefined behavior to try to modify the data in that constant.)
Type casting constness onto or off of things is something I consider bad practice - there is generally nothing wrong with passing a non-const pointer into a function expecting a const one.
The exception is if there is some reason that the data can change part way through the execution (e.g. another thread touching the data pointed at) - then you might have a problem, but its not the sort of problem that typecasting will prevent. In this case you need to make your logic thread safe.
Don't forget that the const keyword can't be used by the compiler to guarantee constness either, although it can be used to detect problems where you think data should not change, but the compiler expects that you want to change it... its more of a documentation tool for you than anything else.
First I assume the & in the myFunction(&p_struct) call is a typo and what you really meant is myFunction(p_struct).
static My_Struct * p_struct = &my_useful_struct;
myFunction(p_struct);
When you pass p_struct there is absolutely no reason to cast the p_struct pointer in the function call. This is perfectly valid to pass a pointer to T in a function where the parameter is pointer to const T.
In the C Standard this is ruled by the constraints of the assignment operator (C99, 6.5.16.1p1). In a function call of a function declared with a prototype, the arguments are converted as if by assignment to the type of the corresponding parameters (C99, 6.5.2.2p7).
This works for me and I don't think the const pointer parameter yields undefined behavior, the compiler does an implicit conversion before calling the function:
typedef struct
{
unsigned char x;
unsigned short y;
unsigned char[NUM_DEFINED_ELSEWHERE];
} My_Struct;
static My_Struct my_useful_struct; // Variables initialized elsewhere in code.
void myFunction(const My_Struct * p_my_struct)
{
/* Performs various read-only actions utilizing p_my_struct. */
}
void myOtherFunction(void)
{
static My_Struct * p_struct = &my_useful_struct;
myFunction(p_struct);
}

How do I quiet the C compiler about a function pointer takes any number of arguments?

I have a function pointer inside a struct that gets dynamically set at runtime to the address of another function in various places in my code. It is defined in my header file like this:
void *(*run)();
During compile time, I get the following warning about this:
warning: function declaration isn't a prototype
This warning is benign, because the pointer is used in many places in my code to call the function it points to, and everything works just fine. However, I would really like to silence the warning.
If I change it to this:
void *(*run)(void);
I get compile errors whever I use it, because the various functions that make use of the pointer have different numbers of arguments, and saying void inside the parenthesies tells the compiler it accepts no arguments.
I can't use a va_list or anything fancy like that, as this is simply a pointer to another function, and I use a single pointer for them all because it keeps the code clean and simple.
I can silence the warning with adding this to my compiler flags:
-Wno-strict-prototypes
But I'd rather not have to disable compiler warnings with flags if I can avoid it.
So my question is: How do I notate this function pointer in the code in such a way that the compiler is satisfied with the fact that it accepts any number of any kind of arguments?
The code works perfectly. I just want the warning to go away.
Store the pointer as a void * and cast to the appropriate function pointer type when necessary? Keep in mind that it isn't necessarily safe to call one type of function pointer as if it were another type, so the warning you're starting out with isn't entirely invalid.
You can cast a function pointer like so:
void *genericPointer = ...;
void (*fp)(int, int) = genericPointer;
fp(123, 456);
Note that:
There's no explicit casting necessary here, as void * can always be cast to any pointer type.
The initial "void" before (*fp) is the return type of the function pointer.
You are trying to do things clean - i.e. involve the compiler in checks, but the design you invented simply cannot be clean by its principle. You cannot involve compiler in prototype checks this way, because you always must know, which parameters to pass at this particular case in runtime. Compiler cannot check this and if you make a mistake, segmentation fault is on the way.
But if I remember well, something like this was maybe used also in linux kernel (?). The solution is to have a general pointer (like the one you have) and each time you call a particular function you just typecast it to the pointer to function with the particular arguments. You may need to typecast it to void * first to silence the compiler again :-)
In C, when you call a function without a prototype visible, default argument promotions are applied to all of the arguments that you pass to the function. This means that the types that you actually pass do not necessarily match the types received by the function.
E.g.
void (*g)();
void f()
{
float x = 0.5;
g(x); // double passed
}
This means that you need to know that the function that you are actually calling has a compatible signature to that implied by the arguments that you are passing after promotion.
Given that you need to know this in any case you must know the function signature of the actual function being called at the call site which is using the function pointer. With this knowledge it is usually simpler and cleaner to use a function pointer with the correct prototype and you can avoid default argument promotion entirely.
Note that as you are defining your functions with prototypes, when you assigned a pointer to your function to a function pointer without a prototype you effective converted, say, a void(*)(int, int) to a void(*)() so it is completely correct and desirable to perform the reverse conversion before calling the function. gcc allows both these conversions without emitting any warnings.
E.g.
void PerformCall( void(*p)() )
{
if (some_condition)
{
// due to extra knowledge I now know p takes two int arguments
// so use a function pointer with the correct prototype.
void(*prototyped_p)(int, int) = p;
prototyped_p( 3, 4 );
}
}
Try typedefing the function pointer declaration and then have the caller explicityly cast it:
typedef void *(*run)();
//when calling...
void my_foo() {}
run r = (run)my_foo;
If the different function signatures are known, use a union. Otherwise, use a pointer of type void (*)(void) (actually, any function pointer type would do) to hold the generic pointer and convert to the proper type when setting the value and calling the code.
Example using a union:
union run_fn
{
void *(*as_unary)(int);
void *(*as_binary)(int, int);
};
struct foo
{
union run_fn run;
};
void *bar(int, int);
struct foo foo;
foo.run.as_binary = bar;
void *baz = foo.run.as_binary(42, -1);
Example using explicit casts:
struct foo
{
void (*run)(void);
};
void *bar(int, int);
struct foo foo;
foo.run = (void *(*)(int, int))bar;
void *baz = ((void *(*)(int, int))foo.run)(42, -1);
Don't use a void * to hold function pointers - such a conversion is unspecified by the ISO C standard and may be unavailable on certain architectures.
Ignoring the warning and using your code as-is is actually also a possibility, but keep in mind that any function argument will be subject to the default argument promotions and it's your responsibility that the promoted arguments properly match the declared parameters.

Assignment of const to non-const in C

In the following:
struct adt { void * A; };
int new_adt(const void * const A)
{
struct adt * r = malloc(sizeof(struct adt));
r->A = A;
}
I get:
warning: assignment discards qualifiers from pointer target type
I know I can use
memcpy(&(r->A), &A, sizeof(void *));
to workaround it, but I must ask: Is there any alternative?
By using const void * const I pretend to say that no changes will be made to the input. Also, now that I think of it, const void * would suffice, wouldn't it? (Since I can't change the pointer so that it affects the caller)
Thanks for taking the time to read.
By using const void * const I pretend to say that no changes will be made to the input.
You have not pretended to say that no changes will be made to the input, you have explicitly told the compiler that you have guaranteed that no changes will be made to the input.
You MUST NOT do what you are doing.
If you never want to modify A through its pointer from adt, then you should make that pointer const as well, i.e.:
struct adt {
const void * A;
};
That will make the error go away.
If you do want to modify A through adt, then new_adt should take a non-const pointer.
Edit: A more general note, which may help:
The const keyword, in general, applies to the type immediately to its left. However, if there is no type to its left, it will apply to the type to the right. So:
const int * A is the same as int const * A (the const applies to the int, not to the pointer), but in int * const A, the const applies to the pointer, not to the int.
There is a more comprehensive explanation on Wikipedia: const-correctness. The 'Pointers and References' section of that page includes an example which covers the various combinations of const and non-const that you can apply to a pointer.
You can cast the const away:
r->A = (void *) A;
The issue, though, is less about how to avoid the warning and more about what you're trying to do. The compiler is warning you because you're telling the compiler that "A" is not writable, but you're trying to store it in a location that defines it as writable. That's generally not OK, semantically.
Imagine that "A" points to a location in your binaries data section; trying to write to it, after casting the const away, will most probably cause a segfault.
So, really, think about what you're trying to do more closely before trying to work around the compiler warning. They're warnings for a good reason.

Resources