C incomplete Type in structs - c

He folks,
i got a problem and a question.
Hopefully u can help and explain me.
first of all i have 2 stucts:
typedef struct {
double x;
double y;
} A;
typedef struct {
unsigned int count;
A(*stack)[];
}B;
this struct B i declare in main() and passing a Pointer of B to a function this will initializ
main(){
B x;
function rr(&x);
}
void rr(B* test) {
test->stack= malloc((4) * sizeof(A)); //4Elements
for (unsigned int i = 0; i < 4; i++) {
(test->stack+ i)->x= 89;
}
}
on this line
(test->stack+ i)->x= 89;
compiler says incomplete Type
i know why it is incomplete cause in struct B their is no dimension.
but array should initialize in function rr
Maybe u understand what i mean and how to solve my problem.
function rr i am not allowed to change.
Greetings
EDIT 1
Thank you for all answers
mabey i schould clearify my problem
typedef struct {
unsigned int count;
A(*stack)[]; // here i want a pointer to an array of A's
}B;
//over main it is declared
void rr(B*);
main(){
B x;
function rr(&x);
}
// this func is not allowed to change
void rr(B* test) {
test->stack= malloc((4) * sizeof(A)); //4Elements
for (unsigned int i = 0; i < 4; i++) {
(test->stack+ i)->x= 89; // error cause incomplete type but i
//have to use this line
}
}
Hope now it is easier to i understand what i want

This declaration:
A(*stack)[];
Says that stack is a pointer to an array of A of unknown size. That is an incomplete type which means it can't be used directly.
It seems like what you actually want is not a pointer to an array, but a pointer to the first member of a dynamic array of A. So declare the member as a pointer:
A *stack;

In the expression:
(test->stack+ i)->x= 89;
before accessing an array via a pointer to an array you must dereference it.
Try:
(*test->stack)[i].x= 89;

You do not know how to use flexible array members.
Simply:
typedef struct {
double x;
double y;
} A;
typedef struct {
size_t count;
A stack[];
}B;
B *createStack(size_t size)
{
B *s = malloc(sizeof(*s) + size * sizeof( s -> stack[0]));
return s;
}
void rr(B* test) {
for (unsigned int i = 0; i < 4; i++) {
(test->stack+ i)->x= 89;
}
}
int main(void)
{
B *stack = createStack(4);
rr(stack);
free(stack);
}
You need only one allocation to mallloc/realloc or free the structure. The array will decay into pointer for your assignment in rr function.

Related

Define pointer to array of int pointers in struct, how to access those ints?

I have the following code:
struct demo{
int *(*p)[];
};
int main() {
struct demo *demo_ptr;
int a = 1;
int b = 2;
int *arr[2];
arr[0] = &a;
arr[1] = &b;
for (int i = 0; i < 2; i++) {
printf("num in array = %d\n", *arr[i]);
}
demo_ptr->p = &arr;
for(int i = 0; i < 2; i++){
printf("num in array = %d\n", demo_ptr->(*p)[i]);
}
}
I'd like to access a and b by demo_ptr. But the code failed. How to assign value to p (a pointer to array of int pointers) declared in a struct, and how to access those ints in array through demo_ptr?
For starters you declared a pointer to an incomplete type
struct demo{
int *(*p)[];
};
So you can not use the sizeof operator to determine the number of elements in the pointed array.
Secondly you defined an uninitialized pointer that has an indeterminate value.
struct demo *demo_ptr;
So again dereferencing this pointer invokes undefined behavior.
You should write for example
struct demo{
int *(*p)[2];
};
and in main
struct demo demo;
//...
demo.p = &arr;
for ( size_t i = 0; i < sizeof( *demo.p ) / sizeof( **demo.p ); i++ )
{
printf( "num in array = %d\n", *( *demo.p )[i]);
}
Try: *(*demo_ptr->p)[i].
The problem was that sub-scripting operator [] has higher priority than dereference operator *. This can be fixed by placing parenthesis around *demo_ptr->p.
Other issue is that demo_ptr points to no object. Initialize it with:
struct demo *demo_ptr = malloc(sizeof *demo_ptr);
In the following:
struct demo{
int *(*p)[];
};
the member p is a pointer to an incomplete array type. The array type is incomplete because no length has been specified. The array element type is int *.
The incomplete array type is not very useful. In my opinion, if the length is not fixed, it would be better to define p as a pointer to pointer to int:
struct demo{
int **p;
};
Then, in main():
demo_ptr->p = arr;
/* assuming arr[0] and arr[1] are valid pointers to int: */
for(int i = 0; i < 2; i++){
printf("num in array = %d\n", *demo_ptr->p[i]);
}
(Note: *demo_ptr->p[i] is equivalent to *((demo_ptr->p)[i]).)
The other problem in main() is that demo_ptr is an uninitialized pointer, so the dereferences above result in undefined behavior. It needs to point to a struct demo or to allocated storage with size at least sizeof (struct demo). For example:
struct demo *demo_ptr;
struct demo demo;
demo_ptr = &demo;

I want to allocate memory to function pointer

I have 2 functions that have same parameters and return type.
Like
int fun1(int a){
return a+1;
}
int fun2(int a){
return a+2;
}
I made a funtion pointer int(*funptr)(int).
And I want to use malloc and make funptr[0] to point fun1, and funptr[1] to point fun2.
So I tried like
int(*funptr)(int)=(int*)malloc(2*sizeof(funptr));
but it doesn't work. What can I do?
What I understand is you need an array of function pointers. Change
int(*funptr)(int)
to
int (*funptr)[2] (int)
and use funptr[0] = fun1; and funptr[1] = fun2;
Alternatively, if you must use allocated memory, you can use a pointer to function pointer
int (**funptr)(int);
and then use accordingly. For ease of use, do use typedef.
typedef int(*funptr)(int);
funptr * fp;
fp = malloc(2* sizeof*fp);
fp[0] = fun1;
fp[1] = fun2;
Just do a simple array of function pointers.
int (*f)[2](int);
f[0] = fun1;
f[1] = fun2;
Use typedefs if you think the declaration syntax is tricky.
Another thing, if you want you can use malloc instead if you want, but Don't cast malloc
Here you actually made a mistake. You should have casted to a function pointer and not an integer pointer. Well, you should not have casted at all. Here it what it should have looked like:
int (**f)(int) = malloc(2 * sizeof *f);
if(!f) { /* Handle error */ }
f[0] = fun1;
f[1] = fun2;
free(f);
You almost certainly do not want to allocate an array of functions pointers dynamically. Bad idea.
If you insist, then first of you must realize that malloc always returns an object pointer of type void*, which is incompatible with function pointers. As is your current senseless cast to int*. So you need to go to some well-defined middle ground in between function pointers and object pointers, like a uintptr_t integer.
It is getting tedious to over and over again tell people to use typedef when working with function pointers, so I'm not gonna do that yet again. This will be messy even with such a typedef.
Given typedef int func_t (int);, an array of function pointers is func_t* arr[2];. However, since you use malloc, you actually need to use a pointer to such an array: func_t* (*funptr)[2].
The malloc call will be malloc(sizeof(func_t*[2])). However, as mentioned you need to cast the result into something that isn't an object pointer and pray that it's still portable: (uintptr_t)malloc(sizeof(func_t*[2]));. This is the least questionable I can come up with.
Then you must cast that one to a pointer to array of function pointer type. (func_t*(*)[2]).
The abomination end result:
typedef int func_t (int);
int main (void)
{
func_t* (*funptr)[2] = (func_t*(*)[2]) (uintptr_t)malloc(sizeof(func_t*[2]));
(*funptr)[0](1);
(*funptr)[1](1);
free(funptr);
}
You cant index function pointers. You need to declare the array of function pointers or pointer to pointer to function
int fun1(int a){
return printf("%s\n",__FUNCTION__);
}
int fun2(int a){
return printf("%s\n",__FUNCTION__);
}
typedef int func(int);
int main()
{
func *farr[2];
farr[0] = fun1;
farr[1] = fun2;
for(int x = 0; x < 20; x++)
{
farr[(rand() & 1)](1);
}
}
or everything together
int fun1(int a){
return printf("%s\n",__FUNCTION__);
}
int fun2(int a){
return printf("%s\n",__FUNCTION__);
}
int fun3(int a){
return printf("%s\n",__FUNCTION__);
}
int fun4(int a){
return printf("%s\n",__FUNCTION__);
}
typedef int func(int);
typedef int (*fa[2])(int);
int main()
{
func *farr[2];
func **fapp = malloc(2*sizeof(*fapp));
fa *fap = malloc(2 * sizeof(*fap));
farr[0] = fun1;
farr[1] = fun2;
fapp[0] = fun1;
fapp[1] = fun2;
fap[0][0] = fun1;
fap[0][1] = fun2;
fap[1][0] = fun3;
fap[1][1] = fun4;
for(int x = 0; x < 20; x++)
{
farr[(rand() & 1)](1);
}
printf("------------------------------\n");
for(int x = 0; x < 20; x++)
{
int x = rand() % 4;
fap[x / 2][x & 1](1);
}
printf("------------------------------\n");
for(int x = 0; x < 20; x++)
{
fapp[rand() & 1](1);
}
}
https://godbolt.org/z/OSFGSp

flexible array member in a nested struct

Is it valid C code to have flexible array members inside nested structs? So is my sample code below guarenteed to work as expected with a sane compiler?
#include <stdio.h>
#include <stdlib.h>
struct d {
char c;
int ns[];
};
struct c {
struct d d;
};
struct b {
struct c c;
};
struct a {
int n;
struct b b;
};
int main() {
const int n = 10;
struct a *pa = malloc(sizeof(*pa) + n * sizeof(pa->b.c.d.ns[0]));
pa->n = n;
pa->b.c.d.c = 1;
for (int i = 0; i < n; ++i) {
pa->b.c.d.ns[i] = i;
}
for (int i = 0; i < n; ++i) {
printf("%d\n", pa->b.c.d.ns[i] + pa->b.c.d.c);
}
free(pa);
}
It's not valid per the standard. I'm not sure how reliable it is in practice.
C11 (ISO/IEC 9899:2011), §6.7.2.1.3 says the following (emphasis mine):
A structure or union shall not contain a member with incomplete or function type (hence, a structure shall not contain an instance of itself, but may contain a pointer to an instance of itself), except that the last member of a structure with more than one named member may have incomplete array type; such a structure (and any union containing, possibly recursively, a member that is such a structure) shall not be a member of a structure or an element of an array.
Later on, §6.7.2.1.18 clarifies that the above is referring to flexible array members (FAMs):
As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member.
From some quick experimentation, GCC and Clang both add the trailing padding required to align the FAM properly even when the struct is nested, and only warn about structures with FAMs being members of other structures or arrays if -Wpedantic is passed, so take that as a sign that it'll probably work if you will :). It feels a bit hackish though.
Note that it probably wouldn't make sense to have the FAM anywhere but at the end. If you do
struct e {
struct d d;
int n;
} e;
, then e.d.ns[0] and e.n are likely to overlap in memory.
Try something like this;
struct d {
char c;
int ns[];
};
struct a {
int n;
int d_fam[];
};
int main() {
const int n = 10;
struct a *pa = malloc(offsetof (struct a, d_fam) + offsetof (stuct d, ns) + n * sizeof(int));
struct d *pd = pa + (uintptr_t) offsetof (struct a, d_fam);
pa->n = n;
pd->c = 1;
for (int i = 0; i < n; ++i) {
pd->ns[i] = i;
}
for (int i = 0; i < n; ++i) {
printf ("%d\n", pd->ns[i] + pd->c);
}
free(pa);
}

Pointer to 2D struct array C

I have a certain struct structXand a 2D array which holds these kind of structs.
I want to be able to save a pointer to that 2D struct and iterate over it
in a dynamic way, meaning, the pointer can hold any structX and iterate.
Example in general lines:
struct structX *ptr = NULL;
...
if(i == OK)
{
ptr = General_struct_which_holds_others->ptr1;
}
else if(i ==NOT_OK)
{
ptr = General_struct_which_holds_others->ptr2;
}
Now the iteration:
if(ptr[x][y] == OK) <----Error, subscripted value is neither array nor pointer
{
...
}
I hope i'm understood, As i was saying this is very general.
How can the iteration be made? meaning not getting errors?
Thanks!
Two problem I can noticce in your code if(ptr[x][y] == OK)
(1):
ptr is pointer to structure (single *) you can't use double indices [][] so error at if(ptr[x][y] == OK)
error, subscripted value is neither array nor pointer because of ptr[][]
(2):
error: used struct type value where scalar is required means if(struct are not allow).
if(should be a scalar value )
scalar value means can be convert into 0/1.
Pointer to 2D struct array C
struct structX matrix2D[ROW][COL];
its pointer
struct structX (*ptr2D)[ROW][COL];
ptr2D = &matrix2D;
ok, access you array structure like this:
struct structX i;
(*ptr2D)[r][c] = i;
If you want to pass in an function do like:
void to(struct structX* ptr2D[][COL]){
struct structX i;
ptr2D[][COL] = i;
}
void from(){
struct structX matrix2D[ROW][COL];
to(matrix2D);
}
Just to make you sure I written a simple code shows how to work with ptr2D. Hope you find it helpful:
#include<stdio.h>
#define ROW 10
#define COL 5
typedef struct {
int a;
char b;
} structX;
void to(structX ptr2D[][COL], int r, int c){
printf("in to: %d %c\n", ptr2D[r][c].a, ptr2D[r][c].b);
}
int main(){
structX matrix[ROW][COL];
structX (*ptr2D)[ROW][COL];
ptr2D = &matrix;
structX i;
i.a = 5;
i.b = 'a';
int r = 3;
int c = 2;
(*ptr2D)[r][c] = i;
printf("%d %c\n", (*ptr2D)[r][c].a, (*ptr2D)[r][c].b);
to(matrix, r, c);
}
And its working, Output:
5 a
in to: 5 a
EDIT
I wanted to show two tricks but now I think I should provide a uniform method(as you commented):
So here is the code:
#include<stdio.h>
#define ROW 10
#define COL 5
typedef struct {
int a;
char b;
} structX;
void to(structX (*ptr2D)[ROW][COL], int r, int c){
printf("in to: %d %c\n", (*ptr2D)[r][c].a, (*ptr2D)[r][c].b);
}
int main(){
structX matrix[ROW][COL];
structX (*ptr2D)[ROW][COL];
ptr2D = &matrix;
structX i;
i.a = 5;
i.b = 'a';
int r = 3;
int c = 2;
(*ptr2D)[r][c] = i;
printf("%d %c\n", (*ptr2D)[r][c].a, (*ptr2D)[r][c].b);
to(&matrix, r, c);
}
Output
5 a
in to: 5 a
EDIT:
error: used struct type value where scalar is required means if(struct are not allow).
if(should be a scalar value )
you can't do like if((*ptr2D)[r][c]);
but this is allow:
if((*ptr2D)[r][c].a == 5);
or
if((*ptr2D)[r][c].b == 'a');
or
if((*ptr2D)[r][c].a == 5 && (*ptr2D)[r][c].b == 'a');
or
structX i;
if((*ptr2D)[r][c] == i);
You might want to ready this article about multidimensional arrays. If you want to iterate over an array, you need to know how big it is (whether it is dynamic or not). If you want it to be dynamic, that means you need to allocate memory for it when it needs to grow and you need to free the old memory. You also have a problem in your question - you declare a single pointer which is null and then try to dereference it but you never allocated memory for it.
If you did allocate memory for it, you could dereference it by saying
ptr[x * ROW_WIDTH + y]
if you set ROW_WIDTH to the maximum value of y. Depending on whether you want to represent a rows major or column major array, you might use y * width instead of x * width.

Function Pointer Array in C

I want to make a function pointer array and be able to call them in a for-loop. How can I achieve this? I have tried:
void (**a) (int);
a[0] = &my_func1;
a[1] = &my_func2;
a[2] = &my_func3;
for ( i = 0; i < 3; i++){
a[0]();
(*a[0])(); // Neither does work
}
But I am missing some syntax I guess:
error: too few arguments to function ‘*(a + (long unsigned int)((long unsigned int)i * 8ul))’
The function you declare is expected to take an int as a parameter:
a[0](1);
Also note that you declare a pointer to pointer for the functions, but you don't allocate any memory for them (I assume this is only in the example) Otherwise it should probably be:
void (*a[3]) (int);
You are declaring that a is a pointer to a pointer to (or an array of pointers to) a function that takes an int as a parameter - so you need to pass an int when you call the functions, e.g. a[0](42);.
I guess the below code is what you need.
typedef void * func_pointer(int);
func_pointer fparr[10];
for(int i = 0; i<10; i++)
{
fparr[i](arg); //pass the integer argument here
}
1) Where have you allocated or defined array to store function addresses?
2) in loop you are always calling (*a[0])();,There should be loop counter
You forgot to give an argument to your function.
void (**a) (int); // here it takes an int argument
a[0] = &my_func1;
a[1] = &my_func2;
a[2] = &my_func3;
for ( i = 0; i < 3; i++){
a[0](); // here you do not give an argument
}
But be careful, you do not allocate memory to your a array, and it fails with a nice segmentation fault error.
void my_func1(int i) {
;
}
void my_func2(int i) {
;
}
void my_func3(int i) {
;
}
int main() {
void (**a) (int);
a = malloc(3*sizeof(void*)); // allocate array !
a[0] = &my_func1;
a[1] = &my_func2;
a[2] = &my_func3;
for (int i = 0; i < 3; i++){
a[i](1); // respect your own function signature
}
free(a); // it's always a good habit to free the memory you take
return 0;
}
You can typedef void (*pfun)(int); and then pfun a[3]; is the array you want.
The following code may work for you:
typedef void (*pfun)(int);
int main() {
pfun a[3];
a[0] = myfunc1; // or &myfunc1 whatever you like
a[1] = myfunc2;
a[2] = myfunc3;
}
You can define your function-array with the needed size and initialize it with your functions like:
void my_func1(int x){}
void my_func2(int x){}
void my_func3(int x){}
void (*a[])(int)={my_func1,my_func2,my_func3};
int i;
for(i=0;i<sizeof a/sizeof*a;++i)
a[i](i);
The address-operator '&' before any function-name is redundant.

Resources