local static variable initialization by using global struct address values - static

My aim is to initialize a local static int variable.
I want to initialize my variable with the value that equals to offset value of a struct member.
My struct definition
struct member{
int ID;
char *NAME;
int NO;
};
Global Struct declaration
struct member FirstMember={.ID = 123, .NAME ="John", .NO=7382737};
struct member SecondMember={.ID = 120, .NAME ="Bill", .NO=454545};
Function and local static variable declaration
void foo()
{
static int offset = (int)(&FirstMember.NO - &SecondMember.ID );
}
Compiler output: Error[Pe028]: expression must have a constant value..
As far as I know static local variables must be initialized with const values. Compiler also knows the address values of the struct and its members. So compiler is able to calculate the difference between member addresses. But it returns an error message.
But this initialization works
void foo()
{
static int offset = (int)(&FirstMember.NO - &FirstMember.ID );
}
Could you please explain the point that I missed?

I think the problem is in your structure declaration: Name shoul be "char *" not "char" because you try to initialize it with "John" (type const char *).
This is working for me:
struct member{
int ID;
char* NAME;
int NO;
};
struct member FirstMember={123,"John",7382737};
void foo()
{
static int offset = (int)(&FirstMember.NO - &FirstMember.ID );
}
The second problem is that you want to initialize a "static" variable with an unknown value before run time.
All the static variables are in a separate place named "initialized data" section and the compiler needs to know exactly the value of each static variable at compile time because these values are "hardcoded" inside your binary file.
Even for this code:
int a = 10;
static int x = a;
you will have the same problem because "a" is not evaluated at compile time but at run-time.

Related

Get address of a static struct member from another header file

I am having trouble putting together some code in which I wish to have the following:
Have a header file myHeader.h in which I create a type struct myStruct with members int number1, int number2 and int number3. This file would also contain a "getter" prototype for getting the address of each of the members in a struct instance.
A translation unit (file.c) in which I declare a static instance of struct myStruct, i.e. static struct myStruct myStructInstance. This translation unit defines the "getter" functions (I will illustrate with a code example at the end of the post).
Another header file anotherHeader.h in which I wish to - now this is a tricky bit that's causing problems for me - get the addresses of each of the members of a static structure and use them for something.
Here's an example to show what I am talking about.
myHeader.h
struct myStruct{
int number1;
int number2;
int number3;
};
int* get_number1(void);
int* get_number2(void);
int* get_number3(void);
file.c
#include <myHeader.h>
static struct myStruct myStructInstance = {
.number1 = 0,
.number2 = 0,
.number3 = 0
};
int* get_number1(void){
struct myStruct* ptr_myStructInstance = &(myStructInstance);
int* number1Address = &(ptr_myStructInstance->number1);
return number1Address;
}
int* get_number2(void){
struct myStruct* ptr_myStructInstance = &(myStructInstance);
int* number2Address = &(ptr_pfcVariables->number2);
return number2Address;
}
int* get_number3(void){
struct myStruct* ptr_myStructInstance = &(myStructInstance);
int* number3Address = &(ptr_myStructInstance->number3);
return number3Address;
}
anotherHeader.h
#include <myHeader.h>
int* pNumber1 = get_number1();
int* pNumber2 = get_number2();
int* pNumber3 = get_number3();
The problem is that the code shown above throws "initializer element is not constant" error in anotherHeader.h. I've read a few answers as to why we cannot use non-constant expressions when initializing variables with static storage duration, however I do not understand how this relates to my code.
I've read a few answers as to why we cannot use non-constant expressions when initializing variables with static storage duration, however I do not understand how this relates to my code.
A function call is a non-constant expression.
int* pNumber1 = get_number1();
The above code is trying to initialize a global variable with a non-constant expression.
You simply can't call code in the global scope.
However, you could easily accomplish the same thing as what you appear to be trying to do by simply extending myHeader.h with:
extern int *pNumber1, *pNumber2, *pNumber3;
and then allocating and initializing these in file.c with:
int *pNumber1 = &myStructInstance.number1,
*pNumber2 = &myStructInstance.number2,
*pNumber3 = &myStructInstance.number3;

Error in initializing members of a structure

Following is a program for initializing members of a structure in c
struct stack
{
int *a;
int top;
int size;
}s;
void init()
{
const int size =10; /*s.size=10;*/ /*const int s.size=10*/
s.a=(int*)malloc(size*sizeof(int));
s.top=0;
}
int main()
{
init();
printf("Initialization done !\n");
return 0;
}
Q1 : In init method instead of const int size=10 when I wrote s.size=10 , I got an error "size was not declared in scope " , but I have already declared size in stack struct .I was able to initialize top in the same manner Then why the error ?
Q2 : In init method I am getting correct output with const int size=10 . I am confused , in this statement how are we able to access size member of the struct stack without using a struct variable , shouldn't it be const int s.size=10?
s.size=10 has no problem. The problem is when you allocate memory for s.a, there's no variable named size, you should change it to:
s.a = malloc(s.size * sizeof(int));
You seem to be confused about the variable size and the member size in the structure struct stack s, they are not related except having the same name.
Yes as size is a structure variable, you have to access with the structure variable and initialize it.
if you initialize size =10 it will take as a new variable. because init function will be stored in a separate stack and the scope of variable size will be inside the init function only.
Then while allocating the memory you should allocate for the s.size variable.
s.a = malloc(s.size * sizeof(int));
I think, your confusion is because you've used the same variable name size twice,
as a structure member variable
as a local variable in void init().
Please be noted, these two are seperate variables.
The size member variable in struct stack is a member of the structure. You need to access a member variable by either . or -> operator [Yes, even if the structure is global].
OTOH, the int size in void init() is a normal variable of type int.
Without having a variable of type struct stack, there does not exist a size, which belongs to struct stack. Likewise, there's no way you can access size, which is a member variable in struct stack directly [without using a structure variable of type struct stack] anywhere.
To summarize
Answer 1:
The error is not for replacing const int size=10 with s.size = 10. It's rather from the next line,
s.a= malloc(size*sizeof(int));
^
|
Where, no size variable is present when const int size=10 is removed.
Answer 2
const int size=10 declares and defines a new variable called size. It's not the same as the s.size [member of struct stack]. That's why using
s.a= malloc(size*sizeof(int));
^
|
is valid, as a variable named size is in scope.
Note: the following method of defining/declaring a struct is depreciated
struct stack
{
int *a;
int top;
int size;
}s;
The preferred method is:
// declare a struct type, named stack
struct stack
{
int *a;
int top;
int size;
};
struct stack s; // declare an instance of the 'struct stack' type
// certain parameters to the compile command can force
// the requirement that all functions (other than main)
// have a prototype so:
void init ( void );
void init()
{
s.size =10;
// get memory allocation for 10 integers
if( NULL == (s.a=(int*)malloc(s.size*sizeof(int)) ) )
{ // then, malloc failed
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
s.top=0;
} // end function: init

Unable to assign values in a structure

I have declared the structure:
typedef struct keyValuePairs{
char* type;
char* key;
char* valueType;
char* value;
} keyValueType;
keyValueType keyValuePairs[1000];
And in a function declared the local variables as:
char key[500];
char value[500];
to hold the key value pair values as:
key[i]="abc";
value[i]="xyz"
I have assigned these local variables to the global variable as:
keyValuepairs[1].key=key.
Once i come out of the function, the values assigned in the structure is getting lost. Can someone explain where I am going wrong?
Please note I am fairly new to C.
Both key and value variables are pointers to arrays that are allocated in the stack when you are in the function. After keyValuepairs[1].key=key the global variable points to that same place in the stack. After exiting the function, the memory where those arrays were is reused.
I suggest you read up on static vs dynamic allocation in C
If I understand you correctly, you are trying something along the lines of:
typedef struct
{
char* val;
} A;
A alist[10];
void foo()
{
char t[10];
t = "abc";
alist[0].val = t;
}
int main()
{
foo();
}
First of all, the line
t = "abc";
is syntactically incorrect. You have to use something like:
strcpy(t, "abc");
But the most important error is that when you return from foo, alist[0].val points to an address that is not good any more. To make sure alist[0].val points to a valid address, you have to allocate memory from the heap for it and copy the contents of t to it.
void foo()
{
char t[10];
strcpy(t,"abc");
alist[0].val = malloc(strlen(t)+1);
strcpy(alist[0].val, t);
}
To do a thorough job, you'll have to make sure that you call free on that allocated memory at some point before you return from main.
You have not allocated memory for type, key, valueType and value.
Try static memory allocation :
typedef struct keyValuePairs{
char* type[n];
char* key[n];
char* valueType[n];
char* value[n];
}
Where n is a defined constant

understanding fs/binfmt_elf.c

i am trying to understand the linux source file /home/akash/Downloads/linux-3.4.3/fs/binfmt_elf.c a part a code is as follows where i hv stuck.
static struct linux_binfmt elf_format = {
.module = THIS_MODULE,
.load_binary = load_elf_binary,
.load_shlib = load_elf_library,
.core_dump = elf_core_dump,
.min_coredump = ELF_EXEC_PAGESIZE,
};
which refer to the file include/linux/binfmt.h
struct linux_binfmt {
struct list_head lh;
struct module *module;
int (*load_binary)(struct linux_binprm *, struct pt_regs * regs);
int (*load_shlib)(struct file *);
int (*core_dump)(struct coredump_params *cprm);
unsigned long min_coredump; /* minimal dump size */
};
plz giv some explaination on this..
It is the initialisation of a structure of type struct linux_binfmt named elf_format (with static storage duration, meaning it exists for the lifetime of the program and is initialised exactly once), using syntax introduced in C99 that allows the specific structure member being initialised to be specified. Prior to C99 the initializer of a struct required the values to be listed in the order the members are declared in the struct.
For example:
struct struct_a { int a; char c; };
In C89 it was not possible to explicitly initialise c only:
struct struct_a s = { 0, 'f' }; /* Have to provide an initial value for
'a', the 0, in order to provide an
initial value for 'c', the f. */
but in C99 the new syntax made it possible:
struct struct_a s = { .c = 'f' };
The types of struct members:
lh is of type struct list_head, which is not explicitly initialised. lh will be default initialised (any members of lh that are pointers are initialized to a null pointer and any arithmetic types will be initialized to zero).
module is of type struct module* and is initialised to THIS_MODULE.
load_binary is a pointer to a function that returns an int and takes arguments of type struct linux_binptrm* and struct pt_regs, and is initialised to a function called load_elf_binary.
load_shlib is a pointer to a function that returns an int and takes an argument of type struct file* and is initialised to a function called load_elf_library.
core_dump is a pointer to a function that returns an int and takes an argument of struct coredump_params* and is initialised to a function called elf_core_dump.
min_coredump is of type unsigned long and is initialised to ELF_EXEC_PAGESIZE.
Refer to section 6.7.8 Initialization of the C99 standard for a full description on initialization syntax and rules.
elf_format is a variable of type linux_binfmt declared as static.
Values assigned for the members of elf_format
.module = THIS_MODULE,
.load_binary = load_elf_binary, /* Function pointer assigned with functions */
.load_shlib = load_elf_library, // do --
.core_dump = elf_core_dump, // do --
.min_coredump = ELF_EXEC_PAGESIZE,

How to apply the sizeof operator to a function pointer and initialize a structure?

The folowing piec of code generates error: initializer element is not constant
at compile time on the line declaring and initializing the user struct variable.
#include <stdio.h>
#include <stdlib.h>
struct user_s {
char *name;
void (*(*pred_skip_func))(int);
};
void f1 (int skip) {
printf("I am f1\n");
}
void f2 (int skip) {
printf("I am f2\n");
}
void (*(*pred_skip_func))(int);
struct user_s user = {"Manu", pred_skip_func};
int main(void) {
struct user_s tmp;
pred_skip_func = malloc(sizeof(tmp.pred_skip_func) * 2);
pred_skip_func[0] = f1;
pred_skip_func[1] = f2;
int i;
for (i = 0; i < 2; i++) {
(*(user.pred_skip_func)[i]) (i);
}
return EXIT_SUCCESS;
}
Moving the initialization in the main function solves the issue, but I want to understand why ? Is there any restriction on structure initialisation ?
More over, as you can see, I created a tmp user_struc variable to get the size of my pointer to function pointers because I was not able to do this in a cleaner way. How can I fix this ?
First question:
"Is there any restriction on structure initialisation ?"
C requires initializers for aggregate types with static storage duration to be constant:
(C99, 6.7.8p4) "All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals."
Note that in C89 even if the object of the aggregate type had automatic storage duration the intializers had to be constant expressions (this is no longer the case in C99).
Second question:
"More over, as you can see, I created a tmp user_struc variable to get the size of my pointer to function pointers because I was not able to do this in a cleaner way."
You can use your user object to compute the size of the member:
sizeof (user.pred_skip_func)
or use a C99 compound literal if you have not declared any object of the structure type:
sizeof (((struct user_s) {0}).pred_skip_func)
As #ouah points out, the problem is that pred_skip_func is not a constant value. The compiler complains because user has static storage duration, which means its bitwise representation is going to be "baked in" the executable image at link time. In order for this representation to be known to the linker the value for pred_skip_func must be a constant.
However, you can specify a "sane default" constant value for the struct member very easily:
struct user_s user = {"Manu", 0};
You can go for typedefs for function pointer like below.
typedef void (*pfunc_type)(int);
struct user_s
{
char *name;
pfunc_type *pred_skip_func;
};
.....
int main (void)
{
.....
pred_skip_func = (pfunc_type *)malloc(sizeof(pfunc_type) * 2);
.....
}
This will increase the readablity of your program.

Resources