I know what container_of() does, but I want to obtain a field that is a pointer within some struct like this:
struct A {
int *ptr;
};
void some_func(int *ptr) {
struct A *a = container_of(&ptr, struct A, ptr);
}
But it seems not working. This is compiled successfully, but looks like it produces wrong pointer:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
struct A {
int *ptr;
};
void some_func(int *ptr)
{
struct A *a = container_of(&ptr, struct A, ptr);
if (a)
pr_info("%d", *a->ptr);
else
pr_info("Ooops");
}
int __init m_init(void)
{
int ptr = 10;
struct A a = {.ptr = &ptr};
some_func(&ptr);
return 0;
}
void __exit m_exit(void)
{
}
module_init(m_init);
module_exit(m_exit);
MODULE_LICENSE("GPL");
If I do container_of(ptr, struct A, ptr); this isn't compiled:
error: static assertion failed: "pointer type mismatch in container_of()"
I guess this is because ptr is a pointer, not a usual int, so __same_type will return false, so make it a pointer.
can anybody help me to fix this?
I will not work. The reason is that ptr in m_init is a local variable, so its address &ptr is meaningless for reconstruction of an address of the other local variable a.
However, you can replace:
some_func(&ptr);
with
some_func(&a.ptr);
But will require changing some_fun to take a pointer int* member of struct A. So the argument type must be int**.
void some_func(int **ptr)
{
if (!ptr) {
pr_info("Ooops");
} else {
struct A *a = container_of(ptr, struct A, ptr);
pr_info("%d", *a->ptr);
}
}
Related
Say that I have a pointer to function theFunc. theFunc takes along a pointer that can point to any function with the same parameter list as theFunc, so the function called can set the passed pointer to NULL or a different function.
Using it would look like this:
while (funcPtr != NULL)
{
funcPtr(&funcPtr);
}
Would defining this be impossible?
Yes, it's doable.
The simple way:
void (*fptr_t)(void*);
The function pointer is data, even though it point to non-data. Therefore a pointer to function pointer can be converted to void* without relying on compiler extensions.
This solution lacks type safety. However, it can be improved.
Currently, it is possible to declare a function taking unspecified number of parameters. It allows to form an incomplete function type. For example:
int foo();
declares a function that returns int and takes unspecified parameters. To have a function taking no parameters use int foo(void).
This allows to declare a function taking a pointer to pointer to incomplete function type:
int foo(int (**)());
// call
int (*fptr)(int (**)()) = foo;
fptr(&fptr);
As mentioned in other answers typedef-ing function types makes the code cleaner.
typedef int foo_aux_f();
typedef int foo_f(foo_aux_f**);
foo_f *fptr = &foo;
fptr(&fptr);
It is possible to improve type safety by nesting the declaration of function types deeper and deeper.
typedef int foo_aux0_f();
typedef int foo_aux1_f(foo_aux0_f**);
typedef int foo_aux2_f(foo_aux1_f**);
typedef int foo_aux3_f(foo_aux2_f**);
typedef int foo_f(foo_aux3_f**);
foo_f fptr = &foo;
fptr(&fptr);
The perfect recursive type would be reached with infinite chain of declaration but in practice 2-3 levels are sufficient.
With some abuse of the syntax of typedef keyword it is possible to squeeze the declaration of this type:
typedef int foo_aux0_f(),
foo_aux1_f(foo_aux0_f**),
foo_aux2_f(foo_aux1_f**),
foo_aux3_f(foo_aux2_f**),
foo_f(foo_aux3_f**);
Unfortunately ... or fortunately, this trick will likely not work in upcoming C23 because the old function declarations without prototypes are planned to be removed from the language making () mean no arguments rather then unspecified number of argument.
Yes, you can pass pointer to pointer to function. The syntax is much easier if you use typedefs.
typedef void somefunc(void);
void func1(void)
{
printf("Func1\r");
}
void func2(void)
{
printf("Func2\r");
}
void swapfunction(somefunc **ptr)
{
if(*ptr == func1) *ptr = func2;
else *ptr = func1;
}
int main(void)
{
somefunc *ptr = NULL;
swapfunction(&ptr);
ptr();
swapfunction(&ptr);
ptr();
}
You can also use function return value:
typedef void somefunc(void);
void func1(void)
{
printf("Func1\r");
}
void func2(void)
{
printf("Func2\r");
}
somefunc *swapfunction(somefunc *ptr)
{
if(!ptr) return func1;
else if (ptr == func1) return func2;
else return NULL;
}
int main(void)
{
somefunc *ptr = NULL;
while(ptr = swapfunction(ptr))
{
ptr();
}
}
Ref your github comment, suggest you use a structure instead of type casting pointers to function pointers, etc. It's not exactly what you are requesting, but kind of.
The code will then look like:
#include <stdio.h>
struct funcArgStruct
{
void (*state)(struct funcArgStruct *);
// int extra_data; // optional
};
typedef struct funcArgStruct funcArg;
void start (funcArg *ptr);
void task1 (funcArg *ptr);
void stop (funcArg *ptr);
/* Implementation of an fsm. */
int main()
{
funcArg ptr_, *ptr = &ptr_;
ptr->state = start;
// ptr->extra_data = 0; // optional
while (ptr->state != NULL)
{
ptr->state(ptr);
}
return 0;
}
void start (funcArg *ptr)
{
ptr->state = task1;
}
void stop (funcArg *ptr)
{
ptr->state = NULL;
}
void task1 (funcArg *ptr)
{
ptr->state = stop;
}
This sort of works:
#include <stdio.h>
void *a(void)
{
printf("Calling a()\n");
return NULL;
}
void *b(void)
{
printf("Calling b()\n");
return a;
}
void *c(void)
{
printf("Calling c()\n");
return b;
}
int main(void)
{
void *(*funcPtr)(void) = &c;
while (funcPtr) {
funcPtr = funcPtr();
}
}
I don't really see good uses, especially in passing the pointer to the function itself as an argument (which I why I omitted it) but whatever floats your boat. You can of course replace the arguments to whatever you need.
You could add a typedef to help out a bit with a type:
typedef void *(*myfunc)(void);
Then you could do the following:
myfunc funcPtr = &c;
// instead of: void *(*funcPtr)(void) = &c;
I don't think any of this is particularly elegant, but it should work.
Note that it doesn't matter if you assign c or &c to myfunc, or whether you return a or &a from one of the functions.
I'm getting this error but I really don't know why.
#include <stdio.h>
static struct str* func(void);
int main(void) {
return 0;
}
static struct str* func(void) {
struct str {
char arimb1 : 4;
char arimb2 : 4;
char arimb3 : 4;
char arimb4 : 4;
}s;
static struct str * ptr;
ptr = &s;
return (ptr);
}
And the error(s) are:
return value type does not match the function type [E0120]
'return': cannot convert from 'func::str *' to 'str *' [C2440]
Thank you all so much!
PS: I'm using Visual Studio (Microsoft) but I've tried also repl c and I'm getting the same error there too.
The reason for the error is that you're declaring the structure within the function. The structure declaration should be outside the function, so that the type struct str is the same in both scopes.
#include <stdio.h>
struct str {
char arimb1 : 4;
char arimb2 : 4;
char arimb3 : 4;
char arimb4 : 4;
};
static struct str* func(void);
int main(void) {
return 0;
}
static struct str* func(void) {
static struct str s;
struct str *ptr;
ptr = &s;
return (ptr);
}
Also, to avoid returning a pointer to an automatic variable, you should declare s to be static. There's no need to make ptr static.
I followed Alex's book on object oriented programming using ansi c.
So far tried to model a very basic string class -
Here's the code:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "class.h"
#include "mystring.h"
extern const void *String_c;
int main() {
String *my = new(String_c, "A random string");
char *text = my->str(my);
printf("String contains %s of length %d", text, my->length(my));
delete(my);
free(text);
return 0;
}
class.h
#ifndef CLASS_H_
#define CLASS_H_
#include <stddef.h>
typedef struct {
size_t size;
void* (*ctor) (void* self, va_list *app);
void (*dtor) (void* self);
} Class;
void* new(const void *class, ...);
void delete(void *object);
#endif /* CLASS_H_ */
class.c
/*
* class.c
*
* Created on: 22-Mar-2014
* Author: nilesh
*/
#include <stdarg.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include "class.h"
void *new(const void *_class, ...) {
printf("\nCreating new\n");
const Class *class = _class;
void *p = calloc(1, class->size);
assert(p);
* (const Class **) p = class;
if(class->ctor) {
va_list ap;
va_start(ap, _class);
p = class->ctor(p, &ap);
va_end(ap);
}
return p;
}
void delete(void *object) {
printf("\nDelete\n");
const Class **class = object;
if(object && *class && (*class)->dtor)
(*class)->dtor(object);
free(object);
object = NULL;
}
mystring.h
#ifndef STRING_H_
#define STRING_H_
#include <stddef.h>
#include "class.h"
typedef struct string String;
struct _string;
struct string {
const Class *class;
struct _string *_;
int (*length) (String *self);
char* (*str) (String *self);
};
extern Class _string_class;
extern const void *String_c;
#endif /* STRING_H_ */
mystring.c
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "mystring.h"
struct _string {
char *data;
int length;
};
static int length(String *self) {
return self->_->length;
}
static char* str(String *self) {
char *ret = malloc(sizeof(char) * self->_->length);
memcpy(ret, self->_->data, sizeof(char)*self->_->length);
return ret;
}
void* ctor(void *_self, va_list *app) {
printf("\nConstructor called\n");
String *self = _self;
self->_ = malloc(sizeof(struct _string));
char *text = va_arg(*app, char *);
self->_->length = strlen(text);
self->_->data = malloc(sizeof(char) * self->_->length);
memcpy(self->_->data, text, sizeof(char) * self->_->length);
self->length = length;
self->str = str;
return self;
}
void dtor(void *_self) {
printf("\nDestructor called\n");
String *self = _self;
free(self->_);
free(self->_->data);
self->_->data = NULL;
}
Class _string_class = {sizeof(String), ctor, dtor};
const void *String_c = &_string_class;
I have one question:
Why does
Class *class = object
In delete not work, while
Class **class = object
Works?
Works in the sense, in former it doesn't call dtor, but calls length and in case of latter, the call to function is (*class)->dtor which works.
The short answer is that class is of type Class **; class->dtor would work only if class were of type Class *.
You're probably getting confused because of the double indirection, so here's a longer explanation:
Think about structures layout. Imagine you have a simple structure like so:
struct example {
int xpto;
char a[10];
}
If you call a function f() and pass it a pointer p to struct example, then f() is free to cast such a pointer to int *. Dereferencing such a pointer yields the same result as p->xpto. That is, p->xpto and *(int *) p are equivalent. This happens because structure components are layed out in increasing memory addresses. xpto is the first member, meaning it's at offset 0. In other words, for any pointer to struct example, the first sizeof(int) bytes at the address pointed to by p belong to xpto.
Your string structure was defined as:
struct string {
const Class *class;
struct _string *_;
int (*length) (String *self);
char* (*str) (String *self);
};
Which shows that at offset 0 of struct string there is a (read-only) pointer to Class. When you call delete(my) in main(), you are giving it a pointer to struct string - thus, the first sizeof(const Class *) bytes in the address pointed to by my are a pointer to a Class. Like we did in the example with struct example - where we casted p to a pointer to the first member - casting such a pointer to Class ** (first member is a Class *, so a pointer to the first member is of type Class **) gives direct access to the first field (and only the first).
Because of that, delete() casts the pointer you give it to a Class **, because by doing so, dereferencing such a pointer yields a Class *.
Why doesn't class->dtor() work? Because class is of type Class **, so, class->dtor, which is equivalent to (*class).dtor is invalid: *class is of type Class *, it's not a structure, and as such, there is no member named dtor. You must use (*class)->dtor, since that's the same as (*(*class)).dtor.
I'm trying to make a generic stack in plain C and I have some problems with pointers and no idea where is the problem.
Here's the structure and functions, where I have problems:
typedef struct{
void *elems;
int elemSize;
int logLength;
int allocLength;
} genStack;
void GenStackPush(genStack *s, const void *elemAddr);
void GenStackPop(genStack *s, void *elemAddr);
That's the implementation:
void GenStackPush(genStack *s, const void *elemAddr)
{
s->elems[s->logLength] = elemAddr;
s->logLength++;
}
void GenStackPop(genStack *s, void *elemAddr)
{
s->logLength--;
elemAddr = s->elems[s->logLength];
}
The usage should look like this:
int val;
genStack IntegerStack;
for (val = 0; val < 6; val++)
GenStackPush(&IntegerStack, &val);
GenStackPop(&IntegerStack, &val);
printf("Popped: %d\n",val);
And here are the problems I get:
genstacklib.c: In function ‘GenStackPush’:
genstacklib.c:60:10: warning: dereferencing ‘void *’ pointer [enabled by default]
genstacklib.c:60:2: error: invalid use of void expression
genstacklib.c: In function ‘GenStackPop’:
genstacklib.c:72:23: warning: dereferencing ‘void *’ pointer [enabled by default]
genstacklib.c:72:13: error: void value not ignored as it ought to be
I have tried already several ways to fix the code, but none of them worked.
Thanks.
==========================================================================
So, guys, thanks for help! Now it compiles, but I have changed an API, which was given by our Professor. There was also the problem with 'const' qualifier, so I deleted them. Not my code looks like this:
genstacklib.h:
#ifndef GENSTACKLIB_H
#define GENSTACKLIB_H
#define GenStackInitialAlocationSize 4
typedef struct{
void** elems;
int elemSize;
int logLength;
int allocLength;
}genStack;
void GenStackNew(genStack *s,int elemSize);
void GenStackDispose(genStack *s);
int GenStackEmpty(const genStack *s);
void GenStackPush(genStack *s, void *elemAddr);
void GenStackPop(genStack *s, void *elemAddr);
#endif
genstacklib.c:
#include <stdlib.h>
#include <stdio.h>
#include "genstacklib.h"
void GenStackNew(genStack *s,int elemSize)
{
void** newElems;
/* Allocate a new array to hold the contents. */
newElems = (void**) malloc(elemSize * GenStackInitialAlocationSize);
if (newElems == NULL)
{
fprintf(stderr, "Error with allocating the stack.\n");
exit(1); /* Exit, returning error code. */
}
s->elems = newElems;
s->allocLength = GenStackInitialAlocationSize;
s->logLength = 0; /*is empty*/
}
void GenStackDispose(genStack *s)
{
s->allocLength = 0;
free(s->elems);
}
int GenStackEmpty(const genStack *s)
{
return s->logLength == 0;
}
void GenStackPush(genStack *s, void *elemAddr)
{
s->elems[s->logLength] = elemAddr;
s->logLength++;
}
void GenStackPop(genStack *s, void *elemAddr)
{
s->logLength--;
elemAddr = s->elems[s->logLength];
}
If you have any ideas to improve it or something to say about it, I would hear with pleasure. :D
you are trying to dereference void pointer without typecasting to some other type which causing the problem.
elems has the wrong type. If you declare it as void* the compiler does not know how big the things it points to are. So it can't do pointer arithmetic or array subscripting on it or even dereference what it points to.
Conceptually elems is an array of the things that you put on the stack. What do you put on the stack? Pointers - declared as void*. So elems should be an array of void* objects. You can declare it like this
typedef struct{
void *elems[STACK_SIZE];
int elemSize;
int logLength;
int allocLength;
} genStack;
which will reserve space in the struct for the array (making the struct itself very big), or you can declare it as a pointer to void* i.e. void**
typedef struct{
void **elems;
int elemSize;
int logLength;
int allocLength;
} genStack;
If you go for this option, you then have to manually allocate the memory
genStack* genStackAlloc()
{
genStack* ret = calloc(1, sizeof *ret);
ret->elemns = calloc(STACK_SIZE, sizeof(void*));
// rest of the initialisation
return ret;
}
And of course, you'll have to manually free the memory when you dispose of the stack.
elems is declared as a pointer to a void, where I think you want it to be a pointer to a void*.
The problem is s->elems[s->logLength] :
First, the member variable void *elems use to store the element address (void *), array of the element (void ), so the type of the elems should be (void *), and you should allocate the memory to store the address.
You can allocate memory by the following ways:
void * elems[MAX_STACK_SIZE];
OR
void ** elems
s->elems = (void**)malloc(MAX_STACK_SIZE*sizeof(void*)); // and allocate it before use it.
In api.h
typedef void* hidden_my_type;
void do_something(my_type x);
In core.c
struct _my_type
{
int a;
}
void do_something(hidden_my_type void_x)
{
struct *_my_type x = void_x; /*Don't understand is that correct way to do, as I'm getting segmentation fault error */
printf("Value: %d\n", x->a);
}
Other way I thought as,
struct *_my_type x = (struct _my_type *)malloc(sizeof(struct _my_type));
void_x = x
printf(Value: %d\n", x->a);
But still I'm getting seg-fault error.
ok here is the problem with void*....
e.g.
in core.c
void init_my_type(hidden_my_type a)
{
my_type *the_a = malloc(...);
a = the_a // <<<<<<<<<<<<<<<<<<<<<<<<<<<< is this correct?! a is void* and the_a // is original type
pthread_cond_init(&the_a->...);
.. (in short any other methods for init ..)
}
void my_type_destroy(my_hidden_type x)
{
my_type *the_x = x;
pthread_detroy(&the_x-> ...);
}
in main.c
test()
{
my_hidden_type x;
init_my_type(x);
....
my_type_detroy(x);
}
this it self should fail. as in main.c test function, x is void* ... init will allocate but in destroy I'm again passing void* .. which can be anything!
EDIT (Solved for me)
In api.h
typedef void* hidden_my_type;
void do_something(my_type x);
In core.c
struct _my_type
{
int a;
}
void init_hidden_type(hidden_my_type void_p_my_type)
{
struct _my_type *real_my_type = (struct _my_type *)malloc(sizeof(struct _my_type));
//--- Do init for your type ---
void_p_my_type = real_my_type;
}
void do_something(hidden_my_type void_x)
{
struct *_my_type x = void_x;
printf("Value: %d\n", x->a);
}
Version 0 — Critique of Question's Code
The posted code does not compile.
api.h
typedef void* hidden_my_type;
void do_something(my_type x);
This defines hidden_my_type but not the my_type that is passed to do_something(). Presumably, you intended:
typedef void *my_type;
void do_something(my_type x);
core.c
struct _my_type
{
int a;
}
As noted below too, there is a semi-colon missing after the structure definition.
void do_something(hidden_my_type void_x)
{
struct *_my_type x = void_x;
printf("Value: %d\n", x->a);
}
You have the hidden_my_type vs my_type problem again. You have the * of the pointer where it cannot go; it must go after the struct _my_type. You probably intended something like:
void do_something(my_type void_x)
{
struct _my_type *x = void_x;
printf("Value: %d\n", x->a);
}
This is now syntactically correct (I think; I haven't actually run it past a compiler). You have not shown how it is used; indeed, since the user code has no way to generate a pointer to a valid structure, there is no way for this code to be used safely.
Your test code (unshown — why don't you show your test code) might look something like this:
#include "api.h"
int main(void)
{
my_type x = 0;
do_something(x);
return 0;
}
Alternatively, it might not have the = 0 initializer in place. Either way, your code is unable to function sanely, and a core dump is almost inevitable. When you hide the structure from the user, you have to provide them with a mechanism to get hold of a valid (pointer to) the structure, and you've not done that.
Version 1
This is a better way to do it, because it is more nearly type-safe:
api.h version 1
typedef struct _my_type *my_type;
void do_something(my_type x);
core.c version 1
#include "api.h"
struct _my_type
{
int a;
};
Note the added semi-colon, and the include of the api.h file.
void do_something(my_type x)
{
// Now you don't have to do casting here!
//struct *_my_type x = void_x; /*Don't understand is that correct way to do, as I'm getting segmentation fault error */
printf("Value: %d\n", x->a);
}
Version 2
Actually, we can debate the wisdom of hiding the pointer; I would prefer not to do so:
api.h version 2
#ifndef API_H_INCLUDED
#define API_H_INCLUDED
typedef struct my_type my_type;
extern void do_something(my_type *x);
extern my_type *my_type_initializer(void);
extern void my_type_release(my_type *x);
#endif /* API_H_INCLUDED */
core.c version 2
#include "api.h"
#include <stdio.h>
#include <stdlib.h>
struct my_type
{
int a;
};
void do_something(my_type *x)
{
printf("Value: %d\n", x->a);
}
my_type *my_type_initializer(void)
{
my_type *x = malloc(sizeof(*x));
x->a = 57; // More plausibly, this would be 0
return x;
}
void my_type_release(my_type *x)
{
free(x);
}
main.c
#include "api.h"
int main(void)
{
my_type *x = my_type_initializer();
do_something(x);
my_type_release(x);
return 0;
}
That's nice and clean. Of course, the user cannot allocate a struct my_type (only a pointer to it), so you need a function to allocate the structure for them. Think of the Standard C Library, and the FILE type, and fopen() to allocate and fclose() to release and fprintf() etc to manipulate the type. The my_type_initializer() is functioning as an analogue to fopen(), my_type_release() as an analogue to fclose(), and do_something() as an analogue to fprintf().
Jonathan, you beat me to an answer, but this may be helpful as well. Here, api.c contains the (private) implementation, and api.h provides the interface to be consumed by other code such as main.c.
// main.c: uses only the public interface to the private code
#include "api.h"
int main(int argc, char *argv[]) {
void *foo;
foo = create_foo("five", 5);
print_foo(foo);
delete_foo(foo);
}
// EOF main.c
// api.h: the public interface
#ifndef _api_h_
#define _api_h_
void *create_foo(char *name, int number);
void print_foo(void *foo);
void delete_foo(void *foo);
#endif // _api_h_
// api.c: the private implementation
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// The real structure is private to the implementation.
typedef struct {
char name[20];
int number;
} real_struct;
// Create a new structure, initialize, return as ptr-to-void.
void *create_foo(char *name, int number) {
real_struct *s = malloc(sizeof(real_struct));
strcpy(s->name, name);
s->number = number;
return (void *) s;
}
// Print the data.
void print_foo(void *foo) {
real_struct *s = (real_struct *) foo;
printf("name: %s, number: %d\n", s->name, s->number);
}
// Release the memory.
void delete_foo(void *foo) {
free(foo);
}
// EOF api.c
This code should compile and run:
$ gcc -o foo main.c api.c
$ ./foo
name: five, number: 5