How to init struct pointer variables with NULL? - c

I have such two struct
struct table_element
{
struct table_val * table_val_arr;
int count_arr;
};
struct hash_table
{
struct table_element table_element_arr[MAX_NUMBER];
};
and here my test method
void test(struct hash_table * table)
{
int count;
struct table_element * tab_element;
for(count = 0; count < MAX_NUMBER; count++)
{
tab_element = &table->table_element_arr[count];
if(tab_element->table_val_arr == NULL)
{
printf("\nNULLLL!!!!!\n");
}
else
{
printf("\nOK!!!!!\n");
}
}
}
and here how I use it
int main(int argc, char **argv)
{
struct hash_table m_hash_table;
test(&m_hash_table);
...
I expect that all value would be NULL, but sometimes I get OK sometimes NULL...
What am I doing wrong?
How to init it with NULL?

Non-static variables defined inside of a function have indeterminate values if not explicitly initialized, meaning you can't rely on anything they may contain.
You can fix this by giving an initializer for the variable:
struct hash_table m_hash_table = {{NULL, 0},{NULL, 0},/*repeat MAX_NUMBER times*/};
Or by using memset:
memset(&m_hash_table, 0, sizeof(m_hash_table));

If you don't explicitly initialise a variable in C, it'll have an undefined value. eg.
int fish; // could be zero, -100, 3805, ...anything
int chips = 5; // will definitely be 5.
The same is true of pointers. They could point anywhere. And finally, the same is true of a structure's members.
There are two common approaches to this 'problem' depending on your needs.
memset the whole thing to zero:
struct hash_table m_hash_table;
memset( &m_hash_table, 0, sizeof(m_hash_table) );
Result: all the variables will be zero, all the pointers will be NULL1.
Explicitly set everything by hand:
struct hash_table m_hash_table;
for (int i = 0; i < MAX_NUMBER; i++)
{
m_hash_table.table_element_arr[i].table_val_arr = NULL;
m_hash_table.table_element_arr[i].count_arr = 0;
}
A third option is to provide initialisation when you declare the struct, but it's logically equivalent to option 2.
struct hash_table m_hash_table = { { NULL, 0 }, { NULL, 0 }, ... /*etc*/ };
1 As per the comments, it is true that there exist some architectures where a bit pattern of all zeros is not equivalent to NULL, and hence the memset( ..., 0, ...) approach is not strictly valid. However, for all practical purposes, on any modern platform, it's a perfectly valid, idiomatic solution.
(IMHO anyone using an architecture where this isn't true isn't going to be looking for advice on SO about how to initialise their structures!)

You declared m_hash_table as an automatic variable. Such variables are usually located on the stack. The stack space may be filled with random content.
You have three options.
Declare it as a static variable: static struct hash_table m_hash_table;
Use memset(): memset(&m_hash_table, 0, sizeof(m_hash_table));
Use explicit initializer: struct hash_table m_hash_table = {};
UPDATE#1
According to this http://c-faq.com/null/machexamp.html information options #1 and #2 do not work correctly on some hardware. The option #3 gives the desired result.
UPDATE#2
The discussion below reveals a new truth. Option #1 is the best.

The struct hash_table m_hash_table; is automatic storage, (vs say, static, in which case it would be automatically initialised.) This means the contents of the variable are indeterminate. One could initialise it several ways, see initialisation, (or the other answers.) However, I think that this is important to know that memset is not a proper way to initialise a null pointer, (the C FAQ has an entire section on null pointers.) Like Pascal's nil or Java's null, 0 in pointer context has a special meaning in C, the null pointer. It commonly is all-bits-zero, leading to the mistaken impression that 0 is actually all-bits-zero, but this is not always the case. The general idiomatic way is to have a constructor in which you set any null pointers with explicit,
te->table_val_arr = 0; /* or NULL. */
te->count_arr = 0;
Edit: three initialisations are shown:
#include <stddef.h>
#include <assert.h>
/* `struct table_val` is undefined in this limited context. */
struct table_element {
int * table_val_arr;
int count_arr;
};
/** `te` is a value that gets initialised to be empty. */
static void table_element(struct table_element *const te) {
assert(te);
te->table_val_arr = 0; /* Or `NULL`, depending on your style. */
te->count_arr = 0;
}
struct hash_table {
struct table_element table_element_arr[100];
};
static size_t hash_table_size =
sizeof ((struct hash_table *)0)->table_element_arr
/ sizeof *((struct hash_table *)0)->table_element_arr;
/** `ht` is a value that gets initialised to be empty. */
static void hash_table(struct hash_table *const ht) {
size_t i;
assert(ht);
for(i = 0; i < hash_table_size; i++)
table_element(ht->table_element_arr + i);
}
/* This is automatically initialised to all-elements-zero, (which is not
necessary all-bits-zero.) */
static struct hash_table g_hash_table;
int main(void) {
struct hash_table m_hash_table = {{{0,0}}}; /* Initialiser. */
struct hash_table table; /* Garbage. */
hash_table(&table); /* Now fixed. */
return 0;
}
The dynamic way of using constructor functions is scalable to large objects and objects that one doesn't want to necessarily initialise with zero; C++ expands this greatly to RAII. The initialisation in the declaration is limited to constant expressions, and thus is probably the most efficient. The static option changes the storage class of the object and is probably unsuitable except for objects that one wanted to declare static anyway.

A colleague (not on SO) has suggested this answer: Partially initializing a C struct
Which says (in essence) if you initialise the first element of your structure, the compiler will automatically initialise everything else to zero or NULL (as appropriate) for you.
Copying from that...
10 If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:
—if it has pointer type, it is initialized to a null pointer;
—if it has arithmetic type, it is initialized to (positive or unsigned) zero;
—if it is an aggregate, every member is initialized (recursively) according to these rules;
—if it is a union, the first named member is initialized (recursively) according to these rules.
...
21 If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

Related

Initialize an empty nested struct using a function

I have to initialize tCoworking coworking by implementing init_coworking function that is declared at the end.
/* Constants *********************************************************/
#define nWorkSpaces 50
#define unlimited 2000
/* Types *************************************************************/
typedef enum {tableFlex, tableFix, officeFix} rate;
typedef char string[55];
typedef struct {
int reservationId;
float monthPayment;
} tContractAnnex;
typedef struct {
int id;
string name;
int discount;
} tPartner;
typedef struct {
int id;
float surface;
rate rateType;
} tWorkspace;
typedef struct {
int partnerId;
int month;
int year;
tContractAnnex annex;
} tContract;
typedef struct {
tWorkspace workSpace[nWorkSpaces];
tContract contract[unlimited];
tPartner partner[unlimited];
} tCoworking;
/* Function declaration */
void init_coworking(tCoworking *coworking);
As you can see the problem I have is that tCoworking is a nested struct with array of stucts as data types..
So far I'm doing this in order to initialize it but it must be a better way to do it.
void init_coworking(tCoworking *coworking){
coworking = malloc(sizeof(tCoworking));
coworking->partner[0].id = 0;
coworking->partner[0].discount = 0;
strcpy(coworking->partner[0].name, "");
coworking->workSpace[0].id = 0;
coworking->workSpace[0].rateType = 0;
coworking->workSpace[0].surface = 0;
coworking->contract[0].partnerId = 0;
coworking->contract[0].year = 0;
coworking->contract[0].month = 0;
coworking->contract[0].annex.monthPayment = 0;
coworking->contract[0].annex.reservationId = 0;
}
void init_coworking(tCoworking *coworking) {
coworking && memset( coworking, 0, sizeof( tCoworking ) );
}
memset initializes a block of memory - of specifiable length - to a single byte value. Your example indicates that you desire zero-initialization of the entire object, so memset serves this purpose well.
NULL-check your input argument.
I recommend you not malloc or calloc in your function because your function signature implies that the caller is the owner of the tCoworking. If you malloc within your init_coworking() function, then you'll have created a new heap-allocated instance of a tCoworking with no clear ownership. You can try keep track of newly-allocated objects in some type of container, but that's going far beyond the scope of your question -- keep it simple.
The simplest way is to use calloc. Like malloc it allocates memory for you but it also sets all the memory to zero.
However - more important is that your current function doesn't make sense. The memory you allocate is simply lost. The caller of init_coworking will never get the allocated and initialized memory.
Either you should:
Not do any malloc(or calloc)
or
Return the malloced pointer.
Since the prototype suggest that you get a tCoworking pointer, the most likely thing is that it's already allocated (in some way), i.e. you want option 1.
So just do:
void init_coworking(tCoworking *coworking){ // NO malloc
memset(coworking, 0, sizeof(tCoworking));
}
In case you only want the first array member set to zero (like your code indicates) you may get a little performance improvement by:
void init_coworking(tCoworking *coworking){ // NO malloc
memset(&coworking->partner[0], 0, sizeof(coworking->partner[0]));
... similar for the other arrays ...
}
but I doubt that's worth the trouble...

User defined types with dynamic size in C

I want to define a new data type consisting of an array with a size inputted by the user. For example if the user inputs 128, then my program should make a new type which is basically an array of 16 bytes. This structure's definition needs to be global since I am going to use that type thereafter in my program. It is necessary to have a dynamic size for this structure because I will have a HUGE database populated by that type of variables in the end.
The code I have right now is:
struct user_defined_integer;
.
.
.
void def_type(int num_bits)
{
extern struct user_defined_integer
{
int val[num_bits/sizeof(int)];
};
return;
}
(which is not working)
The closest thing to my question, I have found, is in here:
I need to make a global array in C with a size inputted by the user
(Which is not helpful)
Is there a way to do this, so that my structure is recognized in the whole file?
When doing:
extern struct user_defined_integer
{
int val[num_bits/sizeof(int)];
};
You should get the warning:
warning: useless storage class specifier in empty declaration
because you have an empty declaration. extern does not apply to user_defined_integer, but rather the variable that comes after it. Secondly, this won't work anyway because a struct that contains a variable length array can't have any linkage.
error: object with variably modified type must have no linkage
Even so, variable length arrays allocate storage at the point of declaration. You should instead opt for dynamic memory.
#include <stdlib.h>
typedef struct
{
int num_bits;
int* val;
} user_defined_integer;
void set_val(user_defined_integer* udi, int num_bits)
{
udi->num_bits = num_bits;
udi->val = malloc(num_bits/sizeof(int));
}
What you need is a VLA member, as asked about here. Basically, you declare a struct with a size field and one element's worth of storage as last member, and over-allocate it.
Imported from that question :
typedef struct Bitmapset {
int nwords;
uint32 words[1];
} Bitmapset;
Bitmapset *allocate(int n) {
Bitmapset *p = malloc(offsetof(Bitmapset, words) + n * sizeof *p->words);
p->nwords = n;
return p;
}
I want to define a new data type consisting of an array with a size inputted by the user. For example if the user inputs 128, then my program should make a new type which is basically an array of 16 bytes.
This is not possible in C, because C types are a compile-time thing and don't exist at all at run-time.
However, with a C99 conforming compiler, you might use flexible array member. You'll need a struct containing some members and ending with an array without any given dimension, e.g.
struct my_flex_st {
unsigned size;
int arr[]; // of size elements
};
Here is a way to allocate it:
struct my_flex_st *make_flex(unsigned siz) {
struct my_flex_st* ptr
= malloc(sizeof(struct my_flex_st) + siz * sizeof(int));
if (!ptr) { perror("malloc my_flex_st"); exit(EXIT_FAILURE); };
ptr->size = siz;
memset (ptr->arr, 0, siz*sizeof(int));
return ptr;
}
Don't forget to free it once you don't use it anymore.
Of course, you'll need to use pointers in your code. If you really want to have a global variable, declare it as e.g.
extern struct my_flex_st* my_glob_ptr;
Try this method-
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
struct user_defined_integer
{
int *val;
}user_int;
void memory_allocate(int num_bit)
{
int result;
result = (num_bit+CHAR_BIT-1)/CHAR_BIT; // since 8 bit =1 byte
user_int.val=malloc(result*sizeof(int));
if(user_int.val == NULL){
printf("Failed to allocate memory\n");
return ;
}
else
printf("Allocated %d bytes for val\n",result);
}
int main()
{
int num_bit;
printf("Enter the number of bits\n");
scanf("%d",&num_bit);
memory_allocate(num_bit);
// do your stuff here
free(user_int.val); // free the memory at the end;
return 0;
}

Variable-length array in file scope?

I have this code for example.
#include <stdlib.h>
#include <stdio.h>
#define array_size 3
typedef struct {
int array[array_size];
} TEST;
void printout(TEST *p, int element) {
printf("element: %i\n", p->array[element]);
}
int main(void) {
TEST *p;
p = malloc(sizeof(TEST));
p->array[0] = 5;
printout(p, 0);
return 0;
}
But I'd like to assign "array_size" based on user input.
If I try to do so, the compiler says "variably modified ‘array_size’ at file scope". So, am I right that the only way to do what I want is to move everything to main()..?
It works just fine, but keeping structs and functions declarations in file scope seems, you know, neat.
The simplest approach is to just allocate the memory dynamically:
typedef struct {
int *array;
size_t size;
} TEST;
int main() {
size_t elem_count = /* from user input */
TEST p;
p->array = malloc(elem_count * sizeof int);
if(!p->array)
return -1;
p->size = elem_count;
/* ... */
free(p->array);
}
You can indeed not define a variable length array at file scope, you can however define a pointer at file scope and malloc it, just define a global pointer int* p = NULL; (lose the whole TEST stuff) and p = malloc(sizeof(int) * input_size); simply access with p[x].
For completeness, you can also use the so called flexible array member defined in C99:
From ISO/IEC 9899:1999, Section 6.7.2.1, paragraph 16:
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.
typedef struct {
other_type other_data
int array[];
} TEST;
...
TEST *p = malloc(sizeof(TEST) + sizeof(int) * input_size);
Though note that this is limited to a single member, you could make an array of structs if you would otherwise have multiple arrays of different types but the same length.
This was originally intended mostly for data with headers such as ofter encountered in file and/or network I/O.

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.

Why can't we initialize members inside a structure?

Why can't we initialize members inside a structure ?
example:
struct s {
int i = 10;
};
If you want to initialize non-static members in struct declaration:
In C++ (not C), structs are almost synonymous to classes and can have members initialized in the constructor.
struct s {
int i;
s(): i(10)
{
}
};
If you want to initialize an instance:
In C or C++:
struct s {
int i;
};
...
struct s s_instance = { 10 };
C99 also has a feature called designated initializers:
struct s {
int i;
};
...
struct s s_instance = {
.i = 10,
};
There is also a GNU C extension which is very similar to C99 designated initializers, but it's better to use something more portable:
struct s s_instance = {
i: 10,
};
The direct answer is because the structure definition declares a type and not a variable that can be initialized. Your example is:
struct s { int i=10; };
This does not declare any variable - it defines a type. To declare a variable, you would add a name between the } and the ;, and then you would initialize it afterwards:
struct s { int i; } t = { 10 };
As Checkers noted, in C99, you can also use designated initializers (which is a wonderful improvement -- one day, C will catch up with the other features that Fortran 66 had for data initialization, primarily repeating initializers a specifiable number of times). With this simple structure, there is no benefit. If you have a structure with, say, 20 members and only needed to initialize one of them (say because you have a flag that indicates that the rest of the structure is, or is not, initialized), it is more useful:
struct s { int i; } t = { .i = 10 };
This notation can also be used to initialize unions, to choose which element of the union is initialized.
Note that in C++ 11, the following declaration is now allowed:
struct s {
int i = 10;
};
This is an old question, but it ranks high in Google and might as well be clarified.
Edit2: This answer was written in 2008 and relates to C++98. The rules for member initialization have changed in subsequent versions of the language.
Edit: The question was originally tagged c++ but the poster said it's regarding c so I re-tagged the question, I'm leaving the answer though...
In C++ a struct is just a class which defaults for public rather than private for members and inheritance.
C++ only allows static const integral members to be initialized inline, other members must be initialized in the constructor, or if the struct is a POD in an initialization list (when declaring the variable).
struct bad {
static int answer = 42; // Error! not const
const char* question = "what is life?"; // Error! not const or integral
};
struct good {
static const int answer = 42; // OK
const char* question;
good()
: question("what is life?") // initialization list
{ }
};
struct pod { // plain old data
int answer;
const char* question;
};
pod p = { 42, "what is life?" };
We can't initialize because when we declared any structure than actually what we do, just inform compiler about their presence i.e no memory allocated for that and if we initialize member with no memory for that. Normally what happens when we initialize any variable that depends on the place where we declared variable compiler allocate memory for that variable.
int a = 10;
if it's auto than in stack memory going to allocate
if it's global than in data sections memory going to allocate
So what memory is required to hold that data but in case of structure no memory is there so not possible to initialize it.
As you said it's just a member not a variable. When you declare a variable the compiler will also provide memory space for those variables where you can put values. In the case a of a struct member the compiler is not giving memory space for it, so you cannot assign values to struct members unless you create a variable of that struct type.

Resources