I declared a Normal Structure In C:
typedef struct arr_struct{
int* original;
int size;
int first[size/2];
int second[size-(size/2)];
};
when compile it gives me:
test.c:11: error: ‘size’ undeclared here (not in a function)
any explanation?
You can't define arrays based on a variable size. The size has to be known at compile time. You'll need to make first and second pointers and dynamically allocate them once size is known.
You're getting the error message because you're trying to use the size member of the struct illegally. For one thing, the struct type definition isn't complete until the closing }, so until then the compiler doesn't know that there's a size member within the struct. For another, you cannot refer to a struct member without a struct instance; when you used the expression size the declarators for first and second, the compiler was looking for a variable named size outside of the struct definition.
It is possible to use a VLA within a struct type, but that's really not the approach you want to take here if you're doing what I think you're doing. Better to make first and second pointers to int and allocate them as necessary (as demonstrated by a couple of the answers above).
int val;
scanf("%d",&val);
int a[val];
The above code actually compiles and runs in my gcc compiler.
The reason for not working inside a struct could be due to the lining up of elements inside a struct whose size can't be determined at compile time. I am not fully sure about it though.
An implementation and usage for what miked said could be (without error checking):
typedef struct
{
int size;
int* first;
int* second;
} arr_struct;
// Prepare an arr_struct for use.
arr_struct foo;
foo.size = 1337;
foo.first = malloc(sizeof(int)*foo.size);
foo.second = malloc(sizeof(int)*(foo.size-foo.size/2));
Do remember to free(foo.first) and free(foo.second) when you're done, though!
The size you provide for an array needs to be a constant expression. You have a couple of choices. One would be to include a couple of pointers, and allocate the space dynamically:
typedef struct {
int* original;
int size;
int *first;
int *second;
} arr_struct;
Another possibility would be to use only one array, and create a pointer to the proper point in it:
typedef struct {
int* original;
int size;
int *second;
int first[];
} arr_struct;
This uses a flexible array member, which is new with C99 -- if you're using an out of date C compiler (e.g., MS VC++) it might not be supported directly1. In any case, this still requires dynamic allocation, but lets you do one large allocation for all the data instead of three separate allocations (one for the struct, and one each for first and second).
arr_struct *my_struct = malloc(sizeof(*my_struct) + size * sizeof(int));
my_struct->second = my_struct->first + size/2;
As an aside, note the syntax for typedef -- as it was, your typedef wasn't defining a name at all.
1The workaround is trivial though -- just define first with a size of 1 and subtract 1 from size in your allocation:
arr_struct *my_struct = malloc(sizeof(*my_struct) + (size-1) * sizeof(int));
In theory, this isn't required to work, but in fact it's just fine with all real compilers, at least AFAIK.
Related
I have looked around but have been unable to find a solution to what must be a well asked question.
Here is the code I have:
#include <stdlib.h>
struct my_struct {
int n;
char s[]
};
int main()
{
struct my_struct ms;
ms.s = malloc(sizeof(char*)*50);
}
and here is the error gcc gives me:
error: invalid use of flexible array member
I can get it to compile if i declare the declaration of s inside the struct to be
char* s
and this is probably a superior implementation (pointer arithmetic is faster than arrays, yes?)
but I thought in c a declaration of
char s[]
is the same as
char* s
The way you have it written now , used to be called the "struct hack", until C99 blessed it as a "flexible array member". The reason you're getting an error (probably anyway) is that it needs to be followed by a semicolon:
#include <stdlib.h>
struct my_struct {
int n;
char s[];
};
When you allocate space for this, you want to allocate the size of the struct plus the amount of space you want for the array:
struct my_struct *s = malloc(sizeof(struct my_struct) + 50);
In this case, the flexible array member is an array of char, and sizeof(char)==1, so you don't need to multiply by its size, but just like any other malloc you'd need to if it was an array of some other type:
struct dyn_array {
int size;
int data[];
};
struct dyn_array* my_array = malloc(sizeof(struct dyn_array) + 100 * sizeof(int));
Edit: This gives a different result from changing the member to a pointer. In that case, you (normally) need two separate allocations, one for the struct itself, and one for the "extra" data to be pointed to by the pointer. Using a flexible array member you can allocate all the data in a single block.
You need to decide what it is you are trying to do first.
If you want to have a struct with a pointer to an [independent] array inside, you have to declare it as
struct my_struct {
int n;
char *s;
};
In this case you can create the actual struct object in any way you please (like an automatic variable, for example)
struct my_struct ms;
and then allocate the memory for the array independently
ms.s = malloc(50 * sizeof *ms.s);
In fact, there's no general need to allocate the array memory dynamically
struct my_struct ms;
char s[50];
ms.s = s;
It all depends on what kind of lifetime you need from these objects. If your struct is automatic, then in most cases the array would also be automatic. If the struct object owns the array memory, there's simply no point in doing otherwise. If the struct itself is dynamic, then the array should also normally be dynamic.
Note that in this case you have two independent memory blocks: the struct and the array.
A completely different approach would be to use the "struct hack" idiom. In this case the array becomes an integral part of the struct. Both reside in a single block of memory. In C99 the struct would be declared as
struct my_struct {
int n;
char s[];
};
and to create an object you'd have to allocate the whole thing dynamically
struct my_struct *ms = malloc(sizeof *ms + 50 * sizeof *ms->s);
The size of memory block in this case is calculated to accommodate the struct members and the trailing array of run-time size.
Note that in this case you have no option to create such struct objects as static or automatic objects. Structs with flexible array members at the end can only be allocated dynamically in C.
Your assumption about pointer aritmetics being faster then arrays is absolutely incorrect. Arrays work through pointer arithmetics by definition, so they are basically the same. Moreover, a genuine array (not decayed to a pointer) is generally a bit faster than a pointer object. Pointer value has to be read from memory, while the array's location in memory is "known" (or "calculated") from the array object itself.
The use of an array of unspecified size is only allowed at the end of a structure, and only works in some compilers. It is a non-standard compiler extension. (Although I think I remember C++0x will be allowing this.)
The array will not be a separate allocation for from the structure though. So you need to allocate all of my_struct, not just the array part.
What I do is simply give the array a small but non-zero size. Usually 4 for character arrays and 2 for wchar_t arrays to preserve 32 bit alignment.
Then you can take the declared size of the array into account, when you do the allocating. I often don't on the theory that the slop is smaller than the granularity that the heap manager works in in any case.
Also, I think you should not be using sizeof(char*) in your allocation.
This is what I would do.
struct my_struct {
int nAllocated;
char s[4]; // waste 32 bits to guarantee alignment and room for a null-terminator
};
int main()
{
struct my_struct * pms;
int cb = sizeof(*pms) + sizeof(pms->s[0])*50;
pms = (struct my_struct*) malloc(cb);
pms->nAllocated = (cb - sizoef(*pms) + sizeof(pms->s)) / sizeof(pms->s[0]);
}
I suspect the compiler doesn't know how much space it will need to allocate for s[], should you choose to declare an automatic variable with it.
I concur with what Ben said, declare your struct
struct my_struct {
int n;
char s[1];
};
Also, to clarify his comment about storage, declaring char *s won't put the struct on the stack (since it is dynamically allocated) and allocate s in the heap, what it will do is interpret the first sizeof(char *) bytes of your array as a pointer, so you won't be operating on the data you think you are, and probably will be fatal.
It is vital to remember that although the operations on pointers and arrays may be implemented the same way, they are not the same thing.
Arrays will resolve to pointers, and here you must define s as char *s. The struct basically is a container, and must (IIRC) be fixed size, so having a dynamically sized array inside of it simply isn't possible. Since you're mallocing the memory anyway, this shouldn't make any difference in what you're after.
Basically you're saying, s will indicate a memory location. Note that you can still access this later using notation like s[0].
pointer arithmetic is faster than arrays, yes?
Not at all - they're actually the same. arrays translate to pointer arithmetics at compile-time.
char test[100];
test[40] = 12;
// translates to: (test now indicates the starting address of the array)
*(test+40) = 12;
Working code of storing array inside a structure in a c, and how to store value in the array elements Please leave comment if you have any doubts, i will clarify at my best
Structure Define:
struct process{
int process_id;
int tau;
double alpha;
int* process_time;
};
Memory Allocation for process structure:
struct process* process_mem_aloc = (struct process*) malloc(temp_number_of_process * sizeof(struct process));
Looping through multiple process and for each process updating process_time dyanamic array
int process_count = 0;
int tick_count = 0;
while(process_count < number_of_process){
//Memory allocation for each array of the process, will be containting size equal to number_of_ticks: can hold any value
(process_mem_aloc + process_count)->process_time = (int*) malloc(number_of_ticks* sizeof(int));
reading data from line by line from a file, storing into process_time array and then printing it from the stored value, next while loop is inside the process while loop
while(tick_count < number_of_ticks){
fgets(line, LINE_LENGTH, file);
*((process_mem_aloc + process_count)->process_time + tick_count) = convertToInteger(line);;
printf("tick_count : %d , number_of_ticks %d\n",tick_count,*((process_mem_aloc + process_count)->process_time + tick_count));
tick_count++;
}
tick_count = 0;
the code generated will be identical (array and ptr). Apart from the fact that the array one wont compile that is
and BTW - do it c++ and use vector
I have a problem ,how to make an array vertextDegree [nbColours] with nbColours elements in it ,but the "nbColours" unknown and I have to get it get it from a file .
look at the code
so what can I do to solve this problem ?
int nbEdges,nbVetices, nbColours ;
typedef struct st_graphVertex
{
int index;
int colour;
int val ;
int vertexDegree[nbColours]; // it won't work because nbColours unknown
// here and I want get it from file in the main
struct st_graphVertex *next;
t_edgeList *out;
}t_grapheVertex;
In C99 there is a special syntax for this, although it is limited to only one array per struct (which is OK in your case) - put the array as the last member, and drop its size, like this:
typedef struct st_graphVertex
{
int index;
int colour;
int val ;
struct st_graphVertex *next;
t_edgeList *out;
int vertexDegree[];
}t_grapheVertex;
Now the size of your array is flexible: you can decide what it should be at runtime. Moreover, different st_graphVertex values can have this size set differently (although in such cases it's typical to put nbColours with the specific size as a field in the same struct).
The "payment" for using this trick is inability to allocate such structs on the stack or in the global or static memory. You must allocate them dynamically, like this:
t_grapheVertex *vertex = malloc(sizeof(t_grapheVertex)+sizeof(int)*nbColours);
You can't do that in pre-C99 or in non-last members. Instead, you can make that member a fixed-size pointer:
int* vertexDegree;
And make it point to an array of appropriate size known at runtime:
myVertex.vertexDegree = malloc(nbColours*sizeof(int));
You can also do it using Struct Hack, which is however similar to what dasblinkenlight told in his answer.
As the question states I am looking to create a struct in C whose total size I do not know at compile time.
For example, I would like to create a struct that contains a count value and an array with count elements. I know this could be implemented as:
typedef struct myStruct{
int count;
int *myArray;
} myStruct;
However, I want this struct to take up one solid block of memory so I could use memcpy() on it at a later point in time. Like this:
typedef struct myStruct{
int count;
int myArray[count];
} myStruct;
It sounds like you're looking for flexible array members:
typedef struct myStruct
{
int count;
int myArray[];
} myStruct;
Then, when you allocate it later:
myStruct *x = malloc(sizeof(myStruct) + n * sizeof(int));
x->count = n;
Yes, you can. If you use C99, there's flexible array members. Otherwise, you can do what Microsoft does. Take your original structure definition and map it to an existing block of memory. Reassign the pointer to point just after the structure definition.
Also, the MS approach would allow multiple members with variable size; you just need to properly update each pointer.
(Note: The "MS approach" is just something encountered often in Windows APIs; I don't know if there's an actual term for the practice.)
I have multiple flexible arrays in s struct in c:
typedef struct
{
int a;
float b;
} Name;
typedef struct
{
int c;
int d;
int e;
} NIM;
typedef struct
{
int age;
int time;
Name name[1];
NIM nim[1];
} EthgenSig;
if we have need to allocate memory like this:
malloc(sizeof(EthgenSig) + sizeof(Name) * 10);
how the memory will be allocated and if we operator name array first and then we operate nim array later, then the nim[1] will overwrite the name array, then how to solve it?
You can't have more than one flexible-array member for the exact reason you pointed out.
At most, if you need your data to be kept all in the same memory block, you can make name and nim pointers and set where they point to the correct locations after allocation (making sure not to break any alignment constraint), but the simplest (and most sensible) thing is to just allocate separately the arrays for name and nim.
This is not so hard to do... the key is to realize that arrays and pointers in C both have very similar properties. In fact, array accessor notation has a direct correspondence to pointer notation:
a[b] == *(a + b);
Note that this has the effect of making the name of the array and the index interchangeable, so this is also true:
a[b] == b[a];
You can use this to achieve the result you want. First, declare a structure with two pointer elements. This provides two pointers that will store the base address of the two arrays:
struct two_blocks {
int *x;
int *y;
}
When you allocate this structure, you'll need to allocate extra space for the bodies of the two arrays:
#define X_SIZE 3
#define Y_SIZE 4
two_blocks *data = (two_blocks *)malloc(sizeof(two_blocks)
+ (sizeof(int) * X_SIZE)
+ (sizeof(int) * Y_SIZE));
And then the final step is to initialize the two array pointers. (These expressions use a lot of pointer type casting to ensure that the pointer arithmetic is done in single bytes. Pointer arithmetic is usually done in units of the size of the object being pointed to, to support the array/pointer equivalence I mentioned above.)
data->x = (int *)(((char *)data) + sizeof(two_blocks));
data->y = (int *)(((char *)data) + sizeof(two_blocks) + X_SIZE * sizeof(int));
From there, the arrays can be used like you'd expect:
data->x[2] = 42;
data->x[2] = 42;
A couple observations
Like Matteo said, be careful with alignment. Using this technique is taking memory layout over from the compiler, which can cause unexpected problems. If this caveat makes no sense to you, then you probably shouldn't use this technique.
One of the rationales for using this technique is that it can simplify memory management by reducing the number of frees you need to manage. If you know that your two arrays, x and y, both have the same lifecycle as their enclosing structure, then this removes one potential type of memory leak. (As well as reduces the chance of memory fragmentation by reducing the number of memory blocks.)
Having an array of size 1 is the same as not having an array at all when it comes to the memory layout of this struct.
You may as well have this:
typedef struct
{
int age;
int time;
Name name;
NIM nim;
} EthgenSig;
But I'm assuming that is not what you want. It is pretty hard to tell what you actually want. But I'm assuming that you actually want this:
typedef struct
{
int age;
int time;
Name* name;
NIM* nim;
} EthgenSig;
foo = malloc(sizeof(EthgenSig);
foo.name = malloc(sizeof(Name)*10);
foo.nim = malloc(sizeof(Nim) * 10);
I'm really new to C programming and I'm still trying to understand the concept of using pointers and using typedef structs.
I have this code snippet below that I need to use in a program:
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
}* pStudentRecord;
I'm not exactly sure what this does - to me it seems similar as using interfaces in Objective-C, but I don't think that's the case.
And then I have this line
pStudentRecord* g_ppRecords;
I basically need to add several pStudentRecord to g_ppRecords based on a number. I understand how to create and allocate memory for an object of type pStudentRecord, but I'm not sure how to actually add multiple objects to g_ppRecords.
defines a pointer to the struct described within the curly bracers, here is a simpler example
typedef struct {
int x;
int y;
}Point,* pPoint;
int main(void) {
Point point = {4,5};
pPoint point_ptr = &point;
printf("%d - %d\n",point.x,point_ptr->x);
pPoint second_point_ptr = malloc(sizeof(Point));
second_point_ptr->x = 5;
free(second_point_ptr);
}
The first declares an unnamed struct, and a type pStudentRecord that is a pointer to it. The second declares g_ppRecords to be a pointer to a pStudentRecord. In other words, a pointer to a pointer to a struct.
It's probably easier to think of the second as an "array of pointers". As such, g_ppRecords[0] may point to a pStudentRecord and g_ppRecords[1] to another one. (Which, in turn, point to a record struct.)
In order to add to it, you will need to know how it stores the pointers, that is, how one might tell how many pointers are stored in it. There either is a size somewhere, which for size N, means at least N * sizeof(pStudentRecord*) of memory is allocated, and g_ppRecords[0] through g_ppRecords[N-1] hold the N items. Or, it's NULL terminated, which for size N, means at least (N+1) * sizeof(pStudentRecord*) of memory is allocated and g_ppRecords[0] through g_ppRecords[N-1] hold the N items, and g_ppRecords[N] holds NULL, marking the end of the string.
After this, it should be straightforward to create or add to a g_ppRecords.
A struct is a compound data type, meaning that it's a variable which contains other variables. You're familiar with Objective C, so you might think of it as being a tiny bit like a 'data only' class; that is, a class with no methods. It's a way to store related information together that you can pass around as a single unit.
Typedef is a way for you to name your own data types as synonyms for the built-in types in C. It makes code more readable and allows the compiler to catch more errors (you're effectively teaching the compiler more about your program's intent.) The classic example is
typedef int BOOL;
(There's no built-in BOOL type in older ANSI C.)
This means you can now do things like:
BOOL state = 1;
and declare functions that take BOOL parameters, then have the compiler make sure you're passing BOOLs even though they're really just ints:
void flipSwitch(BOOL isOn); /* function declaration */
...
int value = 0;
BOOL boolValue = 1;
flipSwitch(value); /* Compiler will error here */
flipSwitch(boolValue); /* But this is OK */
So your typedef above is creating a synonym for a student record struct, so you can pass around student records without having to call them struct StudentRecord every time. It makes for cleaner and more readable code. Except that there's more to it here, in your example. What I've just described is:
typedef struct {
char * firstName;
char * lastName;
int id;
float mark;
} StudentRecord;
You can now do things like:
StudentRecord aStudent = { "Angus\n", "Young\n", 1, 4.0 };
or
void writeToParents(StudentRecord student) {
...
}
But you've got a * after the typedef. That's because you want to typedef a data type which holds a pointer to a StudentRecord, not typedef the StudentRecord itself. Eh? Read on...
You need this pointer to StudentRecord because if you want to pass StudentRecords around and be able to modify their member variables, you need to pass around pointers to them, not the variables themselves. typedefs are great for this because, again, the compiler can catch subtle errors. Above we made writeToParents which just reads the contents of the StudentRecord. Say we want to change their grade; we can't set up a function with a simple StudentRecord parameter because we can't change the members directly. So, we need a pointer:
void changeGrade(StudentRecord *student, float newGrade) {
student->mark = newGrade;
}
Easy to see that you might miss the *, so instead, typedef a pointer type for StudentRecord and the compiler will help:
typedef struct { /* as above */ } *PStudentRecord;
Now:
void changeGrade(PStudentRecord student, float newGrade) {
student->mark = newGrade;
}
It's more common to declare both at the same time:
typedef struct {
/* Members */
} StudentRecord, *PStudentRecord;
This gives you both the plain struct typedef and a pointer typedef too.
What's a pointer, then? A variable which holds the address in memory of another variable. Sounds simple; it is, on the face of it, but it gets very subtle and involved very quickly. Try this tutorial
This defines the name of a pointer to the structure but not a name for the structure itself.
Try changing to:
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
} StudentRecord;
StudentRecord foo;
StudentRecord *pfoo = &foo;