I have come across an array with only one element. This array is defined inside a structure. Which goes like this:
typedef struct abc
{
int variable1;
char variable2;
float array[1];
};
I don't understand why this array is required, why can't we define just a variable or define a pointer(considering array property).
I want to use it. How do i use this variable? abc.array[0] seems correct. Isn't it.
Addition I am not using any dynamic memory allocation then what is its significance ?
It's probably what is called the "struct hack". By allocating a large block of memory, the array becomes dynamic. The one element is just a placeholder to make it compile, in fact there will be many floats.
The dynamic array has to be the last element.
Use like this:
struct abc *ptr = malloc(sizeof(struct abc) + (N-1) * sizeof(float));
ptr->variable1 = N; /* usually store length somewhere in struct*/
Related
I have an array of structs, which is dynamically allocated. A pointer to this array is passed around to other functions.
struct body{
char* name;
double mass;
// ... some more stuff
};
body *bodies = malloc(Number_of_bodies*sizeof(body));
I need to know the size of the array, so I'm storing the size in one of the structs, which is in the 0th element of the array (the first struct).
bodies[0].mass = (double)Number_of_bodies;
I then return from the function a pointer to the 1st element of the array i.e bodies[1]
return (bodies+1);
Now, when I use this pointer in other functions, the data should start at the 0th element.
body *new_bodies = (bodies+1); //Just trying to show what happens effectively when i pass to another function
new_bodies[0] = *(bodies+1); //I Think
If I want to see the initial struct, which was at bodies[0], does that mean in other functions I have to access new_bodies[-1] ?
Is this something I can do?
How can I access the initial struct?
Yes, you can use new_bodies[-1] to access the initial element of the array. This is perfectly legal.
The reason behind this is pointer arithmetic: square brackets is another way of writing +, so when you write new_bodies[-1] it is the same as *(new_bodies-1).
Since new_bodies has been obtained as bodies+1, new_bodies-1 is (bodies+1)-1, or bodies, making new_bodies[-1] identical to bodies[0].
Note: It looks like you are trying to shoehorn the number of elements into the initial element of the array of your structs, re-purposing the mass field for it. This will work, but it is suboptimal, both in terms of memory allocation (a pointer name remains unused) but most importantly in terms of readability. You would be a lot better off using a flexible array member in a struct that stores the number of entries explicitly:
struct body {
char* name;
double mass;
// ... some more stuff
};
struct bodies {
size_t count;
body bodies[]; // <<== Flexible array member
};
...
bodies *bb = malloc(sizeof(bodies)+Number_of_bodies*sizeof(body));
bb->count = Number_of_bodies;
Here is a link to another Q&A with an example of working with flexible array members.
I am trying to create a 2d Array at compile time that has an unknown number of rows that i can dynamically allocate throughout the program but a specific number of columns as 8.
Something like ---->Elements[?][8];
If you have to use 2d array instead of list of array you gonna have to make a array
constant i = 1
foo[i][8]
and every time you want to expand that array
make temp_foo[i][8]
copy foo to temp_foo
delete foo
make foo[i++][8]
copy temp_foo to foo
But that's make confusing. and i think its better if use link list
struct node
{
foo[8]
node *next;
}
adding first element
node *element_head
element->foo = {add elements}
element->next = null
adding new element
node *temp
temp->foo = {add element}
temp->next = element_head
element_head= temp
Knowing the number of columns, and making only the number of rows dynamic you can either use a VLA or dynamic allocation. A VLA is straight forward:
int rows;
// get rows somehow
int table[rows][8];
Keeping in mind a VLA has automatic storage lifetime and will be removed from addressable memory once the enclosing scope expires. And they cannot be globals.
If your implementation doesn't support VLA's, automatic storage space is a concern, or you need a global variable for some nefarious purpose, you'll have to manage this dynamically (which it sounds like you want to do anyway). To do that, declare a pointer to an array of 8 elements, as such:
int rows;
// get rows somehow
int (*table)[8] = malloc(rows * sizeof(*table));
The rest is straight forward. You can reference your elements as table[i][j] for i in 0..rows-1 and j in 0..7. Just remember to free your allocation when finished:
free(table);
and don't reference it again.
As far as I know, you can't have foo[][8] in C. You might be able to hack around it by making a struct and casting a pointer to that struct to an array, as discussed here, but that is a somewhat fragile hack.
What you can do is change the definition of rows and columns in your problem space, so that, in order to access row i, column j, you would do foo[j][i] instead of foo[i][j].
In this case you could declare your array like this: <typename> * foo[8].
I'd go with this approach when the dimensions are unknown.
Assuming data type to be int.
int* a; //this will point to your 2D array
allocate it when you know the dimensions (ROW, COL):
a = malloc(sizeof(int)*ROW*COL);
and access it like
a[ROW*i + j] = value // equivalent of a[i][j]
I think it will not be created when you are not passing any value at compile time, my suggestion is to use dynamic memory allocation as you don't know how many rows
It's said that zero length array is for variable length structure, which I can understand. But what puzzle me is why we don't simply use a pointer, we can dereference and allocate a different size structure in the same way.
EDIT - Added example from comments
Assuming:
struct p
{
char ch;
int *arr;
};
We can use this:
struct p *p = malloc(sizeof(*p) + (sizeof(int) * n));
p->arr = (struct p*)(p + 1);
To get a contiguous chunk of memory. However, I seemed to forget the space p->arr occupies and it seems to be a disparate thing from the zero size array method.
If you use a pointer, the structure would no longer be of variable length: it will have fixed length, but its data will be stored in a different place.
The idea behind zero-length arrays* is to store the data of the array "in line" with the rest of the data in the structure, so that the array's data follows the structure's data in memory. Pointer to a separately allocated region of memory does not let you do that.
* Such arrays are also known as flexible arrays; in C99 you declare them as element_type flexArray[] instead of element_type flexArray[0], i.e. you drop zero.
The pointer isn't really needed, so it costs space for no benefit. Also, it might imply another level of indirection, which also isn't really needed.
Compare these example declarations, for a dynamic integer array:
typedef struct {
size_t length;
int data[0];
} IntArray1;
and:
typedef struct {
size_t length;
int *data;
} IntArray2;
Basically, the pointer expresses "the first element of the array is at this address, which can be anything" which is more generic than is typically needed. The desired model is "the first element of the array is right here, but I don't know how large the array is".
Of course, the second form makes it possible to grow the array without risking that the "base" address (the address of the IntArray2 structure itself) changes, which can be really neat. You can't do that with IntArray1, since you need to allocate the base structure and the integer data elements together. Trade-offs, trade-offs ...
These are various forms of the so-called "struct hack", discussed in question 2.6 of the comp.lang.c FAQ.
Defining an array of size 0 is actually illegal in C, and has been at least since the 1989 ANSI standard. Some compilers permit it as an extension, but relying on that leads to non-portable code.
A more portable way to implement this is to use an array of length 1, for example:
struct foo {
size_t len;
char str[1];
};
You could allocate more than sizeof (struct foo) bytes, using len to keep track of the allocated size, and then access str[N] to get the Nth element of the array. Since C compilers typically don't do array bounds checking, this would generally "work". But, strictly speaking, the behavior is undefined.
The 1999 ISO standard added a feature called "flexible array members", intended to replace this usage:
struct foo {
size_t len;
char str[];
};
You can deal with these in the same way as the older struct hack, but the behavior is well defined. But you have to do all the bookkeeping yourself; sizeof (struct foo) still doesn't include the size of the array, for example.
You can, of course, use a pointer instead:
struct bar {
size_t len;
char *ptr;
};
And this is a perfectly good approach, but it has different semantics. The main advantage of the "struct hack", or of flexible array members, is that the array is allocated contiguously with the rest of the structure, and you can copy the array along with the structure using memcpy (as long as the target has been properly allocated). With a pointer, the array is allocated separately -- which may or may not be exactly what you want.
This is because with a pointer you need a separate allocation and assignment.
struct WithPointer
{
int someOtherField;
...
int* array;
};
struct WithArray
{
int someOtherField;
...
int array[1];
};
To get an 'object' of WithPointer you need to do:
struct WithPointer* withPointer = malloc(sizeof(struct WithPointer));
withPointer.array = malloc(ARRAY_SIZE * sizeof(int));
To get an 'object' of WithArray:
struct WithArray* withArray = malloc(sizeof(struct WithArray) +
(ARRAY_SIZE - 1) * sizeof(int));
That's it.
In some cases it's also very handy, or even necessary, to have the array in consecutive memory; for example in network protocol packets.
I have a struct in my c code of about 300Bytes (5xint + 256chars), and I wish to have a good mechanism of array for handling all my 'objects' of this struct.
I want to have a global array of pointers, so that at first all indices in the array points to NULL, but then i initialize each index when I need it (malloc) and delete it when im done with it (free).
typedef struct myfiles mf;
mf* myArr[1000];
Is that what Im looking for? Pointers mixed with arrays often confuse me.
If so, just to clerify, does
mf myArr[1000];
already allocates 1000 structs on the stack, where my first suggestion only allocates 1000pointers?
You are correct. Former allocates 1000 pointers, none of which are initialized, latter initializes 1000 objects of ~300 bytes each.
To initalize to null: foo_t* foo[1000] = {NULL};
But this is still silly. Why not just mf* myArr = NULL? Now you have one pointer to uninitialized memory instead of 1000 pointers to initialized memory and one pointer to keep track of. Would you rather do
myArraySingle = malloc(sizeof(mf)*1000); or
for(int i = 0; i < 1000; i++) {
myArray[i] = malloc(1000);
}
And access by myArraySingle[300] or *(myArray[300])`? Anyway my point is syntax aside don't create this unnecessary indirection. A single pointer can point to a contiguous chunk of memory that holds a sequence of objects, much like an array, which is why pointers support array-style syntax and why array indices start at 0.
typedef struct myfiles mf;
mf* myArr[1000];
This is what you are looking for. This will allocate array of 1000 pointers to the structure mf.
You seem to understand correctly.
More accurately, I believe mf* myArr[1000] = { 0 }; would better meet your requirements, because you want a guarantee that all of the elements will be initialised to null pointers. Without an initialisation, that guarantee doesn't exist.
There is no "global" in C. You're referring to objects with static storage duration, declared at file scope.
typedef struct myfiles mf;
mf* myArr[1000];
yes, it will initialize 1000 pointers, you have to allocate memory to each one using malloc/calloc before use.
How to copy typedef struct into another one?
If I have a typedef struct called books and I have a struct variable called books first. Now I declare books second How can I pass the content of first to second? Is there a function to do that or I can do that just with second = first ?
If your structure does not contain any members that are pointers (or containing structs that do), then you can simply assign one to the other.
second = first;
If however your structs do contain pointers, then with a simple assignment you end up with two struct that contain pointers to the same memory, and changing one will affect the other. If that's not what you want then you need to do a deep copy.
For example:
struct book {
char *name;
int cost; // in cents, so you don't have to deal with floating point issues
};
struct book first;
first.name = strdup("title1");
first.cost = 500;
struct book second;
second.name = strdup(first.name);
second.cost = first.cost;
If both first and second have the same type, then you can just do second = first; . It does not matter whether the type is an built-in or user-defined. C will copy the contents of first over to second. Just try it.
In general, variables in C are just data with a name and a type.
If the types of 2 variables a and b match, you can assign one to the other: a = b;.
What happens is that the value of variable b is copied into variable a.
But beware of pointers: For C, pointers are just variables with a value (the fact that the value represents a memory address does not matter, C treats all data equal).
If the 2 variables happen to be pointers, like char *a; char *b; then you can assign a = b; just with any variable.
But since the value of the variable b is the memory address, the memory address is copied from b to a, not the content of the memory at the memory address.
If you want to have the memory copied over, you will have to do it on your own, e.g. via the help of memcpy() (see its man page for information).
That said, if your structs contain pointers, the pointers are the content, not the stuff the pointers point to. C would copy the pointer values, not the pointer targets.
If you got pointers in your structs and want some sort of deep-copy, you would have to implement the traversal of your structs on your own. See What is the difference between a deep copy and a shallow copy?