Declaring variables inside a struct in c [duplicate] - c

This question already has answers here:
Why can't we initialize members inside a structure?
(6 answers)
Closed 7 years ago.
I wanted to make an object oriented preprocessor to my programming language which converts my language into C (like early C++). And I want to simulate the classes with structures. And the question is: how can I declare a variable inside a struct like this:
typedef struct { //equivalent of class
int a = 5;
int (*sub)(int) = &int_sub; //function of a class, uses an external declared function
} class_name;
I tried the code above but the compiler wrote this:
error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘=’ token
void (*sub)(int) = &int_sub;
I have two questions:
Can I declare a variable inside a struct?
If yes, how?

You can't assign a pointer value inside a struct definition. You could use a function to init it.
typedef struct { //equivalent of class
int a;
int (*sub)(int);
} class_name;
int int_sub (int a)
{
// your stuff
return 0;
}
int main()
{
class_name myClassVariable;
myClassVariable.a = 5;
myClassVariable.sub = int_sub;
printf("class_name.a = %d\n", myClassVariable.a );
printf("class_name.sub = %p\n", myClassVariable.sub );
printf("int_sub address = %p\n", int_sub );
return 0;
}
Or, as shown in artm answer, you could init your allocated variable:
class_name my_struct = { .a = 5, .sub = int_sub };

Alternatively, you can also initialize the variable of your struct type.
int func( int a ){}
typedef struct {
int a;
int (*sub)(int);
} class_name;
class_name my_struct = { .a = 5, .sub = func };

I take it your question is not about how to declare but how to initialize a structure member.
Define the class as opaque type in the h file. Use typedef for function pointers.
h file
// opaque type declaration
typedef struct class_name class_name;
// types used by this class
typedef int sub_func_t (int);
// member functions of the class
class_name* class_init (int a, sub_func_t* sub);
Then initialize it from inside its constructor:
c file
struct class_name { //equivalent of class
int a;
sub_func_t* sub;
};
class_name* class_init (int a, sub_func_t* sub)
{
class_name* new_class = malloc(sizeof(*new_class));
assert(new_class != NULL);
*new_class = (class_name){a, sub};
return new_class;
}

Related

Problem Getting Float Pointer and Int from Native C to Dart

I have a basic FFI call that retrieves a C struct from Dart. Only the char * and int * fields of the struct are returning proper values. The float * and int are returning the wrong values. The C and Dart code is below along with the output.
If I were to print the two bad types out on the C side, they do yield proper values.
C Code
// C code
typedef struct {
float * floatPtr;
int count;
char * name;
int * intPtr;
}baseStruct;
baseStruct getMyStruct(){
static baseStruct myStruct;
static int someint = 22;
static float foo [] = {0.1, 0.2, 0.3};
myStruct.floatPtr = foo;
myStruct.count = 0;
myStruct.intPtr = &someint;
myStruct.name = "some string";
return myStruct;
}
Dart Code
// Dart Type for C struct
class MyStructType extends Struct {
external Pointer<Float> floatPtr;
#Int32()
external int count;
external Pointer<Int> intPtr; //worked
external Pointer<Utf8> name; //worked
}
// type defs for FFI
typedef GetMyStructNative = MyStructType Function();
typedef GetMyStruct = MyStructType Function();
// Code to call function from dynamic library
static final getMyStruct = module
.lookupFunction<GetMyStructNative, GetMyStruct>('getMyStruct');
// call native function and get native struct
MyStructType myStruct = getMyStruct();
/***************************** OUTPUT *************************/
final count = myStruct.count;
print("count: $count"); // prints some big number like 475423 that's not 0 (incorrect)
final intPtr = myStruct.intPtr.value;
print("count: $intPtr"); // prints 22 (correct)
final name = myStruct.name.toDartString();
print("name: $name"); // prints 'some string' (correct)
final floatPtr myStruct.floatPtr.asTypedList(3);
print("floatPtr: $floatPtr"); // prints [0.0, 0.0, 4.764414778704378e-44] (incorrect)
Got this answer from #blaugold on github. The order of the fields in the structs must match. So changing the dart struct as below fixes the problem.
class MyStructType extends Struct {
external Pointer<Float> floatPtr;
// Int32 -> Int
#Int()
external int count;
// The order of fields matters, so `name` and `intPtr` need to be flipped.
external Pointer<Utf8> name;
external Pointer<Int> intPtr;
}

Tagged structure initialization, functions and their parameters

Many Kernel modules seem to opt for the following struct initialization style;
struct file_operations sample_fops = {
.owner = THIS_MODULE,
.read = sample_read,
.write = sample_write,
.ioctl = sample_ioctl,
.open = sample_open,
.release = sample_release,
};
I can wrap my head around when this style is used for primitives and pointer data types but I can't figure out how they work so seamlessly for functions.
When and where are the parameters for this type of initialization created? Is it in the scope of the file or in the scope where the struct is utilized. Can you access the parameters (for instance a pointer to buffer passed as an argument to the write function) or do you have to initialize the struct in a different style in order to be able to do that?
Furthermore, if sample_fops is called multiple times, is it the same struct throughout the file? And where is it kept in the memory during its lifetime? Are the parameters kept in the same place too?
I have not exactly understood your question but this is
struct file_operations sample_fops = {
.owner = THIS_MODULE,
.read = sample_read,
.write = sample_write,
.ioctl = sample_ioctl,
.open = sample_open,
.release = sample_release,
};
a declaration of the object sample_fops that has the type struct file_operations.
It seems that the data members of the structure are declared as pointers to functions and in this declaration function designators as for example sample_open are used to initializa corresponding data members of the structure.
Here is a demonstrative program.
#include <stdio.h>
void f( void )
{
puts( "Hello Yusuf Gürkan Bor" );
}
struct A
{
void ( *hello )( void );
};
int main( void )
{
struct A a = { .hello = f };
a.hello();
}
The program output is
Hello Yusuf Gürkan Bor
This record in the initializarion .fp = f is called a designation initialization.
It uses the name of a data member of a structure that is initialized.
In fact you can equivalently to write
struct A a = { f };
But for a such an initialization you have to keep the order of initializers relative to the order of data members.
Here is another example when a function accepts an argument.
#include <stdio.h>
void f( const char *name )
{
printf( "Hello %s\n", name );
}
struct A
{
void ( *hello )( const char * );
};
int main( void )
{
struct A a = { .hello = f };
a.hello( "Yusuf Gürkan Bor" );
}
Its output is the same as shown above.
The following snippet:
int main ()
{
typedef struct ArrayType
{
int field1;
int field2;
};
struct ArrayType myArray =
{
.field1 = 0,
.field2 = 1,
};
}
is equivalent to
int main ()
{
typedef struct ArrayType
{
int field1;
int field2;
};
ArrayType myArray;
myArray.field1 = 0;
myArray.field2 = 1;
}
if you have a pointer to function, this can work as well.
int function1(int a,int b){ return a+b};
void function2(int c) {};
int main ()
{
typedef struct ArrayType
{
int(*function1)(int,int);
void(*function2)(int);
};
ArrayType myArray;
myArray.function1= thisFunction;
myArray.function2= thatFunction;
}

How to make static variable in a structure in C

I want to make a structure in C with one of the structure variable having an initial default value
struct process{
char process_name[2];
int burst_time;
int completion_time;
int turn_around_time;
int waiting_time;
int priority;
int arrival_time= 0;
};
in the above structure, i want to make arrival_time=0 but i gives me an error
Priority.c:11:19: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘=’ token
In C, it's not possible. You can't initialize structure members inside a structure itself. First you need to create an instance or variable of the structure type; only after that can you initialize a structure member. For example:
struct process{
char process_name[2];
int burst_time;
int completion_time;
int turn_around_time;
int waiting_time;
int priority;
int arrival_time; /* here you can't initialize */
} process_instance = { .arrival_time = 0 }; /* first process_instance created then initialize the members */
And you can access like arrival_time like below.
int main(void) {
printf("%d\'n",process_instance.arrival_time);
return 0;
}
Though in C++ (not in C), structs are almost synonymous to classes and can have members initialized in the constructor. For example:
struct process{
int arrival_time; /* member of structure */
process() : arrival_time(0) { } /*constructor */
};
int main(void) {
process obj;
std::cout<<obj.arrival_time;
return 0;
}

Why do My C Code go Wrong

The below is my code. Compiler generates the errors as
#include<stdio.h>
struct Shelf{
int clothes;
int *books;
};
struct Shelf b;
b.clothes=5;
*(b.books)=6;
Compiler generates the errors as below for both statements b.clothes=5; and b->books=6; in above code.
error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘->’ token
I'm not a beginner at C and I believe that what I have written is correct. Kindly solve my problem
FIRST
You cannot do this
struct Shelf{
int clothes;
int books;
};
struct Shelf b;
b.clothes=5;
b.books=6;
In global scope
You can assign value inside a function
int main (void )
{
b.clothes=5;
b.books=6;
}
Or initializing values on declaration
struct Shelf b = { .clothes = 5, .books = 6 };
Moreover as you can see b is not a pointer so using -> is not correct: use . to access members of struct.
SECOND
Your struct has a pointer member book
struct Shelf{
int clothes;
int *books;
};
What you can do is to set it to the address of another variable, like
int book = 6;
struct Shelf b = { .clothes = 5, .books = &book };
Or allocate memory for that pointer like
int main (void )
{
b.clothes=5;
b.books=malloc(sizeof(int));
if (b.books != NULL)
{
*(b.books) = 6;
}
}
BTW I guess you want an array of books, so
int main (void )
{
b.clothes=5;
b.books=malloc(sizeof(int) * MAX_N_OF_BOOKS);
if (b.books != NULL)
{
for (int i=0; i<MAX_N_OF_BOOKS; i++)
b.books[i] = 6;
}
}
COMPETE TEST CODE
#include <stdio.h>
#include <stdlib.h>
struct Shelf
{
int clothes;
int *books;
};
int main(void)
{
struct Shelf b;
b.clothes = 5;
b.books = malloc(sizeof(int));
if (b.books != NULL)
{
*(b.books) = 6;
}
printf ("clothes: %d\n", b.clothes);
printf ("book: %d\n", *(b.books) );
}
OUTPUT
clothes: 5
book: 6
b is a struct, not a pointer, so -> is not correct.
It's like doing (*b).books, which is wrong.
struct Shelf{
int clothes;
int *books;
};
One data member of the struct is a pointer, however:
struct Shelf b;
is not a pointer, it is just a struct as I said before.
As for your question in comment:
b.clothes=5;
is correct. Also something like this would be ok:
int number = 6;
b.books = &number;
-> operator used to access of member of struct via pointer. b is not dynamically allocated so b->books=6; is wrong. You should first allocate memory for member books and then dereference it.
b.books = malloc(sizeof(int));
*(b.books)= 6;

Initializing a Struct of a Struct

If I have a struct in C that has an integer and an array, how do I initialize the integer to 0 and the first element of the array to 0, if the struct is a member another struct so that for every instance of the other struct the integer and the array has those initialized values?
Initialisers can be nested for nested structs, e.g.
typedef struct {
int j;
} Foo;
typedef struct {
int i;
Foo f;
} Bar;
Bar b = { 0, { 0 } };
I hope this sample program helps....
#include <stdio.h>
typedef struct
{
int a;
int b[10];
}xx;
typedef struct
{
xx x1;
char b;
}yy;
int main()
{
yy zz = {{0, {1,2,3}}, 'A'};
printf("\n %d %d %d %c\n", zz.x1.a, zz.x1.b[0], zz.x1.b[1], zz.b);
return 0;
}
yy zz = {{0, {0}}, 'A'}; will initialize all the elements of array b[10] will be set to 0.
Like #unwind suggestion, In C all instances created should initialized manually. No constructor kind of mechanism here.
You can 0-initialize the whole struct with {0}.
For example:
typedef struct {
char myStr[5];
} Foo;
typedef struct {
Foo f;
} Bar;
Bar b = {0}; // this line initializes all members of b to 0, including all characters in myStr.
C doesn't have constructors, so unless you are using an initializer expression in every case, i.e. write something like
my_big_struct = { { 0, 0 } };
to initialize the inner structure, you're going to have to add a function and make sure it's called in all cases where the structure is "instantiated":
my_big_struct a;
init_inner_struct(&a.inner_struct);
Here is an alternative example how you would do things like this with object-oriented design. Please note that this example uses runtime initialization.
mystruct.h
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
typedef struct mystruct_t mystruct_t; // "opaque" type
const mystruct_t* mystruct_construct (void);
void mystruct_print (const mystruct_t* my);
void mystruct_destruct (const mystruct_t* my);
#endif
mystruct.c
#include "mystruct.h"
#include <stdlib.h>
#include <stdio.h>
struct mystruct_t // implementation of opaque type
{
int x; // private variable
int y; // private variable
};
const mystruct_t* mystruct_construct (void)
{
mystruct_t* my = malloc(sizeof(mystruct_t));
if(my == NULL)
{
; // error handling needs to be implemented
}
my->x = 1;
my->y = 2;
return my;
}
void mystruct_print (const mystruct_t* my)
{
printf("%d %d\n", my->x, my->y);
}
void mystruct_destruct (const mystruct_t* my)
{
free( (void*)my );
}
main.c
int main (void)
{
const mystruct_t* x = mystruct_construct();
mystruct_print(x);
mystruct_destruct(x);
return 0;
}
You don't necessarily need to use malloc, you can use a private, statically allocated memory pool as well.

Resources