how to scanf a global variable outside the main? - c

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.

Related

Limitations in "struct inside struct"

There are 2 struct definitions A and A. I know that there is OK to struct A contain a POINTER to struct A but I don't understand why struct A cannot contains struct A (not a pointer)
Because when you put structs inside each other, you're putting another copy of that struct into the struct at that point. For example:
struct A {
int q;
int w;
};
struct B {
int x;
struct A y;
int z;
};
This will be laid out in memory like this:
int /*B.*/x;
int /*A.*/q;
int /*A.*/w;
int /*B.*/z;
But if you try to put a struct inside itself:
struct A {
int x;
struct A y;
};
you have an A, which contains an int and another A, which contains an int and another A, and now you have an infinite number of ints.
Because in that case, it will take infinite storage as it will have to recursively store the data member of its own type. So, it is not possible. Whereas, Size of a pointer is fixed and hence causes no problem.
Let's suppose it could contain an object of its own type:
struct A_
{
A_ a;
int b;
} A;
What's sizeof(A) ? Answer: sizeof(A)+sizeof(int): impossible.
Because the structure definition is not finished until the closing curly-brace }. To declare a structure member the compiler need the full definition, as it uses that information to calculate things like space and padding and alignment etc. For a pointer to something the size of the pointer is the size of the pointer, and all the compiler needs os the name of the type, not its full definition.
Lets take a simple structure for example:
struct A // Here the compiler knows that there is a structure named A
// The compiler does not know its contents, nor its size
{
// Some members...
struct A *pointer_to_a; // All the compiler needs to know is the symbol A
// The size and alignment is that of a pointer
// and those are known by the compiler
// Some more members...
// struct A instance_of_A; // This is not possible! At this point the
// compiler doesn't have the full definition
// of the structure, and can therefore not
// know how much space it need to allocate
// for the member
// Some even more members...
}
// Now the compiler knows the full contents of the structure, its size
// and alignment requirements
;

Is it possible create arrays without declaring the specific size in struct?

Trying to create a struct that contains three arrays. I'm unsure of how large to make the arrays until the input is read.
How can i initialize these arrays in the struct if i'm unsure how large they are going to be in the struct init? I will know the total amount from the first line of input.
I would be the size that is read in from the use input. Should I just make i a huge number?
struct TaskSet
{
float priority[i];
float p[i];
float w[i];
float d[i];
};
You can either use a huge number or use T *arr (together with the size):
struct TaskSet
{
float *priority;
int size_priority;
...
float *d;
int size_d;
};
P.S.: You need to use malloc with the size once read from the user.
A struct needs to be a known size at compile-time so that the compiler knows how much space to give each one in memory. Consider the following struct:
struct pair{
int a;
int b;
};
When you create a struct as a function variable, the compiler creates enough space for two ints on the stack. If you create an array of five structs (see below) the compiler creates enough space for 2*5=10 contiguous ints on the stack:
struct pair p[5];
It is not possible for the compiler to create a struct on the stack if it does not know the size of the struct ahead of time.
Pointers are always the same size, so I recommend using a struct of pointers, like in herohuyongtao's sample code.

Is it possible to create a struct whose size is not known at compile time?

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.)

invalid use of flexible array -flexible struct array as a member of another struct

I'm beginning to learn about the use of structs in C. It's challenging and enjoyable. Needless to say I've encountered a problem I can't seem to figure out. I'm trying to make a flexible struct array as a member of another struct but I'm getting an error:
invalid use of flexible array
What am I doing wrong?
#define NUM_CHANNELS 4
struct channelStruct {
float volume;
uint mute;
};
struct enginestruct
{
float bpm;
int synctimeinbeats;
int synctimeinsamples;
int currentbeat;
int oneBeatInSamples;
int samplerate;
struct channelStruct channels[];
};
struct enginestruct engine, *engineptr;
struct channelStruct channel, *channelptr;
-(void) setupengine
{
engineptr = &engine;
engineptr->oneBeatInSamples = 22050;
engineptr->samplerate = 44100;
struct channelStruct *ch = (struct channelStruct *) malloc (
NUM_CHANNELS*sizeof(struct channelStruct) );
//error occurs here
engineptr->channels = ch;
}
EDIT 1
It's something like this I am trying to achieve
flexible length struct array inside another struct using C
EDIT 2*
O.K so I seem to be approaching the creation of a variable sized array of struct the wrong way. I have 2 things that I'm trying. The first I know works for sure. The second I would just like if somebody could sanity check it for me. I'm still learning about pointers and would like to know if A is the same as B. B would be my preferred method but I don't know if its correct. I'm confident about a because when I debug channels i see channel[0],channel[1]channel[2] etc. But I'm not so confident about B because when I debug it I only see an address to memory and the variables of channel struct listed.
A
// pretty sure this is o.k to do but I would prefer
// not to have to set the size at compile time.
struct enginestruct
{
float bpm;
int synctimeinbeats;
int synctimeinsamples;
int currentbeat;
int oneBeatInSamples;
int samplerate;
channel channels[NUM_CHANNELS]; //is this technically a pointer?
};
B
//I'm not sure if this is valid. Could somebody confirm for me if
//it is allocating the same amount of space as in A.
struct enginestruct
{
float bpm;
int synctimeinbeats;
int synctimeinsamples;
int currentbeat;
int oneBeatInSamples;
int samplerate;
channel *channels;
};
//This only works if channel in the engine struct is defined as a pointer.
channel * ar = malloc(sizeof(*ar) * NUM_CHANNELS);
engineptr->channels = ar;
**EDIT 3****
Yep they are the same. Not sure when you would use one over the other tho
channel channels[NUM_CHANNELS];
Is Equal To :)
struct enginestruct
{
float bpm;
int synctimeinbeats;
int synctimeinsamples;
int currentbeat;
int oneBeatInSamples;
int samplerate;
channel *channels;
};
channel * ar = malloc(sizeof(*ar) * NUM_CHANNELS);
engineptr->channels = ar;
Edit
I think I remember now what the problem is. When you declare a struct with a flexible array as it's last member it's doing something completely different than what you think.
struct channelStruct channels[];
is NOT a pointer, it is an in place array which is contiguous with the struct.
The way this is intended to be used is to lay the struct over an existing block memory. For instance, this is useful in networking when you have a packet with variable length data. So you might do something like:
struct mydata {
// various other data fields
int varDataSize;
char data[];
}
When you receive a packet you cast a pointer to the data to a mydata pointer and then the varDataSize field tells you how much you've got. Like I said, the thing to remember is that it's all one contiguous block of memory and data is NOT a pointer.
Old Answer:
I think that's only allow in the C99 standard. Try compiling with the -std=c99 flag.
Also, see this thread, Variable array in struct
Also see this SO post: Flexible array members in C - bad?
I am not an expert in this C feature but my common sense tells me that you cannot define objects of the type struct enginestruct, only pointers. This regards the engine variable in the following line:
struct enginestruct engine,*engineptr;

variable declaration problem inside struct

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.

Resources