How do I use an array variable inside an array of structures? - c

I'm trying to grasp the concept of arrays of structures and came up with a problem. Hopefully you can help me out.
Okay, so, the problem I'm facing is how to declare and use (i.e. accept & display values) of an array variable within an array of structures?
This sample code may visually help you to understand my problem:
#include<stdio.h>
struct node{
int roll;
char name[10];
int grades[5]; // Accepts 5 grades for each student
};
int main()
{
struct node student[3];
/*Accept and display values for structure members here*/
return 0;
}
I know there's a similar example here.
But I don't understand line 4 in the accepted answer's main() section, where memory is allocated using malloc() :
list[ip].inputs[inp]= (char*)malloc(25);
I'm getting confused between the 25 bytes allocated here and the 10 defined in char* inputs[10];
What exactly is happening here? And how do you solve the problem I mentioned above?

There's an extra * in the example you quote. The malloc is needed only because of that, in your example inputs is an array of 10 pointers to char while here name is a buffer holding 10 chars. You don't need any malloc in your code.
Your structure looks like this in memory (assuming 4-bytes ints):
Your student array from main looks like:
As you see, fields are laid out one after another. Thus, to read the name of the first student you have to write into student[0].name (using strncpy to ensure that there's no overflow). To change the third letter of the name of the second student you'll use student[1].name[2].

You can safely use it like this:
strcpy(student[1].name, "Yu Hao");
student[1].grades[1] = 95;
printf("student 1 name: %s\n", student[1].name);
printf("student1 grades1:%d\n", student[1].grades[1]);
The example you linked uses malloc because the struct has some pointers, and pointers have to point to somewhere valid before using. That's not the case in your example.
Note that using strcpy can lead to disaster when you copy a string longer than 10, if that's to consider, use strncpy instead.

To answer the question related to the referred post.
First, hope you have basic knowledge about pointers in C.
A pointer is indeed a memory address for short.
For details I recomend you this booklet (a very excellent introduction about arrays and poiners).
In that piece of codes, the inputs is defined as char* inputs[10];.
It's an array of pointers.
So each elment in that array should be an address.
The argument 25 in the malloc invokation is not necessary (you can also specify 40 or 50 to meet your requirement).
The only thing you should guarantee is that each element in the array is an address (that's what malloc returns).
The 10 specifies array dimension, i.e. you can store 10 addresses in total in inputs or say, you can initialize the array by invoking malloc ten times like:
struct a;
for (int i = 0; i < 10; i++) {
a.inputs[i] = (char *) malloc(25);
}
Back to your own problem.
In your case, the symbol name identifies the address to the storage.
No need for you to malloc new storage.

Related

Dynamically declaring structs not working as expected [duplicate]

This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 5 years ago.
I'm having issues with my program, and I'm trying to break it down and I'm seeing that I'm having issues with memory allocation at a minimum.
I have a struct:
typedef struct{
int originX;
int originY;
char ticBoard[3][3];
int result;
int turn;
} simBoard;
I would expect the size of this struct (one single instance of it) to be (4 ints * 4 bytes) + (1 bye char * 3 * 3) or 25 bytes. When I run the sizeof() function on simBoard, I get a value of 28 bytes. I'm assuming that it's the 25 + 3 extra that I don't need to worry about.
The main issue is when I try to declare an array of this struct
simBoard* boardArray = (simBoard*)malloc(sizeof(simBoard)*size));
Assume size is some constant for this scenario. To my knowledge this should create an array of the simBoard struct, of size size. I should be able to go
boardArray[3]
And get the 4th item of boardArray correct? However I'm running into an issue with the memory allocation. When I run:
printf("%zu is the size of the array\n", sizeof(boardArray));
The return value is 8. I even tried to further sort out the issue:
simBoard* boardArray = (simBoard*)malloc(224);
When I ran the printf again, I'm still getting a value of 8 bytes for boardArray. If you guys could lead me in the right direction that'd be fantastic, as I'm absolutely stumped here.
Thank you!
You can indeed index the 4th struct in the array using the notation boardArray[3].
Bear in mind though that boardArray itself is a pointer type. That explains your printf output. Arrays with dynamic storage duration and pointer types are inextricably linked in C. For the avoidance of doubt, sizeof(boardArray) is sizeof(simBoard*).
C doesn't provide functionality to obtain the length of an dynamic array. You need to remember the length yourself.
Don't forget to call free(boardArray) when your done. The C runtime library will take appropriate measures to ensure that all the struct elements are freed.

C struct malloc & array of pointers implementation

I just started programming in C a few days ago. I am now trying to learn structs.
I have this program and I want to improve it so that my array people is now an array of pointers to structs. I am not sure how to do this.
I also want to modify my insert method, to call malloc to create a new struct and set the correct array element pointing to it.
As far as I know, malloc is dinamic memory allocation but although I've read some guides I'm still unsure on how exactly to use it. Also, after using malloc, what else do I need to change in my program for it to work as before?
If you want people to be an array of pointers, you have to declare it like this:
struct person *people[12];
Remember that declaration follows use and that dereferencing has lower precedence than array indexing; this means that *people[i] is of type struct person, and thus, people[i] is a pointer to struct person.
To initialize each position in people, you call malloc() to make your pointers point to a valid memory location large enough to hold a struct person. It is as easy as:
people[i] = malloc(sizeof(struct person));
When you don't need people anymore, you have to remember to free every memory position you allocated, by calling free(people[i]) for every position i.
I noticed you declared the array to hold 12 structs. This can be dangerous when someone changes the code: it will not work when HOW_MANY is greater than 12. You should declare an array of the same size:
struct person *people[HOW_MANY];
This ensures that your array always has exactly the space needed.
UPDATE:
You need to declare insert as receiving an array of pointers instead of an array of structures:
static void insert (struct person *people[], char *name, int age) {
... }
And people[i].name is invalid. Since people[i] is a pointer now, you need to do it like this:
people[i]->name
Or, equivalently, (*people[i]).name.
The same applies to people[i]->age. Remember to change this both in main() and inside insert.
Also, consider passing i to insert instead of using static variables, unless you have a very good reason to do so. Static variables are used for functions with internal state, and for me, insert is not quite the type of function where you'd want that.

C Multidimensional Character Array Initialization

I'm fairly new to C and I'm trying to wrap my head around the initialization of a multidimensional character array, for my assignment I'm asked to read from a file and store the text in an array,
I have to read input for 5 fictitious people and store some information about them, so I realized that my array will look something like:
char input[5][];
What I am confused about is the second parameter, I'm not sure what to set it too. There are 9 fields of information which I will be storing about these people, and I can't seem to find an answer to if I should set this second number to the amount of fields, or how large it should be. ie,
char input[5][9];
or
char input[5][256];
Also, if it's the latter, is there a practice of how larger I should set it to, or just pick a number? Thanks!
I suggest you take the following approach: instead of making an array of char to store the information about these persons, you should make a struct person, which would have some info variable with predefined lenght
struct person {
char name[50];
char address[50];
char phone_number[15];
};
or, if you want, you can make these char pointers (such like char *name, char *address), and then you can malloc() the desired amount of memory to each variable as you want (also, don't forget to free the memory after you use it).
Then, in your main, you could make an array of persons, such as struct person[5];, and manipulate them as you want.
edit: Also note that, as Pankrates commented, when you define a size for your array you must make sure that the input will not exceed the lenght of the array, otherwise you'll be writing stuff on memory that does not belong to you, which causes undefined behavior.
To figure this you should try to learn about the input. If you are absolutely sure there will be only 9 fields(of single char data) for 5 people, then you should set it to char input[5][9].
If you think there could be more fields of information than 9 in the future, then you could go for a higher value like char input[5][256]. However this would waste a lot of space if the data for fields are sparse. This is static assignment of memory
So the third option when you are unsure about the number of fields for each person, is to assign memory dynamically like--
char* input[5];
input[0] = malloc(sizeof(char) * 100); // space of 100 chars
Here in the last case, the memory is given at runtime instead of compile time. You can also get the size from user input and use it for assign memory for fields.
char* input[5];
int size = 0;
scanf("%d",&size);
input[0] = malloc(sizeof(char) * size);
Further more, if you need to store fields, where each field takes more than one character then you should create a structure.
struct person
{ char name[30]; // memory could be assigned dynamically or statically
char field1[30];
char field2[30];
...
};

a few beginner C questions

I'm sort of learning C, I'm not a beginner to programming though, I "know" Java and python, and by the way I'm on a mac (leopard).
Firstly,
1: could someone explain when to use a pointer and when not to?
2:
char *fun = malloc(sizeof(char) * 4);
or
char fun[4];
or
char *fun = "fun";
And then all but the last would set indexes 0, 1, 2 and 3 to 'f', 'u', 'n' and '\0' respectively. My question is, why isn't the second one a pointer? Why char fun[4] and not char *fun[4]? And how come it seems that a pointer to a struct or an int is always an array?
3:
I understand this:
typedef struct car
{
...
};
is a shortcut for
struct car
{
...
};
typedef struct car car;
Correct? But something I am really confused about:
typedef struct A
{
...
}B;
What is the difference between A and B? A is the 'tag-name', but what's that? When do I use which? Same thing for enums.
4. I understand what pointers do, but I don't understand what the point of them is (no pun intended). And when does something get allocated on the stack vs. the heap? How do I know where it gets allocated? Do pointers have something to do with it?
5. And lastly, know any good tutorial for C game programming (simple) ? And for mac/OS X, not windows?
PS. Is there any other name people use to refer to just C, not C++? I hate how they're all named almost the same thing, so hard to try to google specifically C and not just get C++ and C# stuff.
Thanks!!
It was hard to pick a best answer, they were all great, but the one I picked was the only one that made me understand my 3rd question, which was the only one I was originally going to ask. Thanks again!
My question is, why isn't the second one a pointer?
Because it declares an array. In the two other cases, you have a pointer that refers to data that lives somewhere else. Your array declaration, however, declares an array of data that lives where it's declared. If you declared it within a function, then data will die when you return from that function. Finally char *fun[4] would be an array of 4 pointers - it wouldn't be a char pointer. In case you just want to point to a block of 4 chars, then char* would fully suffice, no need to tell it that there are exactly 4 chars to be pointed to.
The first way which creates an object on the heap is used if you need data to live from thereon until the matching free call. The data will survive a return from a function.
The last way just creates data that's not intended to be written to. It's a pointer which refers to a string literal - it's often stored in read-only memory. If you write to it, then the behavior is undefined.
I understand what pointers do, but I don't understand what the point of them is (no pun intended).
Pointers are used to point to something (no pun, of course). Look at it like this: If you have a row of items on the table, and your friend says "pick the second item", then the item won't magically walk its way to you. You have to grab it. Your hand acts like a pointer, and when you move your hand back to you, you dereference that pointer and get the item. The row of items can be seen as an array of items:
And how come it seems that a pointer to a struct or an int is always an array?
item row[5];
When you do item i = row[1]; then you first point your hand at the first item (get a pointer to the first one), and then you advance till you are at the second item. Then you take your hand with the item back to you :) So, the row[1] syntax is not something special to arrays, but rather special to pointers - it's equivalent to *(row + 1), and a temporary pointer is made up when you use an array like that.
What is the difference between A and B? A is the 'tag-name', but what's that? When do I use which? Same thing for enums.
typedef struct car
{
...
};
That's not valid code. You basically said "define the type struct car { ... } to be referable by the following ordinary identifier" but you missed to tell it the identifier. The two following snippets are equivalent instead, as far as i can see
1)
struct car
{
...
};
typedef struct car car;
2)
typedef struct car
{
...
} car;
What is the difference between A and B? A is the 'tag-name', but what's that? When do I use which? Same thing for enums.
In our case, the identifier car was declared two times in the same scope. But the declarations won't conflict because each of the identifiers are in a different namespace. The two namespaces involved are the ordinary namespace and the tag namespace. A tag identifier needs to be used after a struct, union or enum keyword, while an ordinary identifier doesn't need anything around it. You may have heard of the POSIX function stat, whose interface looks like the following
struct stat {
...
};
int stat(const char *path, struct stat *buf);
In that code snippet, stat is registered into the two aforementioned namespaces too. struct stat will refer to the struct, and merely stat will refer to the function. Some people don't like to precede identifiers always with struct, union or enum. Those use typedef to introduce an ordinary identifier that will refer to the struct too. The identifier can of course be the same (both times car), or they can differ (one time A the other time B). It doesn't matter.
3) It's bad style to use two different names A and B:
typedef struct A
{
...
} B;
With that definition, you can say
struct A a;
B b;
b.field = 42;
a.field = b.field;
because the variables a and b have the same type. C programmers usually say
typedef struct A
{
...
} A;
so that you can use "A" as a type name, equivalent to "struct A" but it saves you a lot of typing.
Use them when you need to. Read some more examples and tutorials until you understand what pointers are, and this ought to be a lot clearer :)
The second case creates an array in memory, with space for four bytes. When you use that array's name, you magically get back a pointer to the first (index 0) element. And then the [] operator then actually works on a pointer, not an array - x[y] is equivalent to *(x + y). And yes, this means x[y] is the same as y[x]. Sorry.
Note also that when you add an integer to a pointer, it's multiplied by the size of the pointed-to elements, so if you do someIntArray[1], you get the second (index 1) element, not somewhere inbetween starting at the first byte.
Also, as a final gotcha - array types in function argument lists - eg, void foo(int bar[4]) - secretly get turned into pointer types - that is, void foo(int *bar). This is only the case in function arguments.
Your third example declares a struct type with two names - struct A and B. In pure C, the struct is mandatory for A - in C++, you can just refer to it as either A or B. Apart from the name change, the two types are completely equivalent, and you can substitute one for the other anywhere, anytime without any change in behavior.
C has three places things can be stored:
The stack - local variables in functions go here. For example:
void foo() {
int x; // on the stack
}
The heap - things go here when you allocate them explicitly with malloc, calloc, or realloc.
void foo() {
int *x; // on the stack
x = malloc(sizeof(*x)); // the value pointed to by x is on the heap
}
Static storage - global variables and static variables, allocated once at program startup.
int x; // static
void foo() {
static int y; // essentially a global that can only be used in foo()
}
No idea. I wish I didn't need to answer all questions at once - this is why you should split them up :)
Note: formatting looks ugly due to some sort of markdown bug, if anyone knows of a workaround please feel free to edit (and remove this note!)
char *fun = malloc(sizeof(char) * 4);
or
char fun[4];
or
char *fun = "fun";
The first one can be set to any size you want at runtime, and be resized later - you can also free the memory when you are done.
The second one is a pointer really 'fun' is the same as char ptr=&fun[0].
I understand what pointers do, but I don't understand what the point of
them is (no pun intended). And when
does something get allocated on the
stack vs. the heap? How do I know
where it gets allocated? Do pointers
have something to do with it?
When you define something in a function like "char fun[4]" it is defined on the stack and the memory isn't available outside the function.
Using malloc (or new in C++) reserves memory on the heap - you can make this data available anywhere in the program by passing it the pointer. This also lets you decide the size of the memory at runtime and finaly the size of the stack is limited (typically 1Mb) while on the heap you can reserve all the memory you have available.
edit 5. Not really - I would say pure C. C++ is (almost) a superset of C so unless you are working on a very limited embedded system it's usualy OK to use C++.
\5. Chipmunk
Fast and lightweight 2D rigid body physics library in C.
Designed with 2D video games in mind.
Lightweight C99 implementation with no external dependencies outside of the Std. C library.
Many language bindings available.
Simple, read the documentation and see!
Unrestrictive MIT license.
Makes you smarter, stronger and more attractive to the opposite gender!
...
In your second question:
char *fun = malloc(sizeof(char) * 4);
vs
char fun[4];
vs
char *fun = "fun";
These all involve an array of 4 chars, but that's where the similarity ends. Where they differ is in the lifetime, modifiability and initialisation of those chars.
The first one creates a single pointer to char object called fun - this pointer variable will live only from when this function starts until the function returns. It also calls the C standard library and asks it to dynamically create a memory block the size of an array of 4 chars, and assigns the location of the first char in the block to fun. This memory block (which you can treat as an array of 4 chars) has a flexible lifetime that's entirely up to the programmer - it lives until you pass that memory location to free(). Note that this means that the memory block created by malloc can live for a longer or shorter time than the pointer variable fun itself does. Note also that the association between fun and that memory block is not fixed - you can change fun so it points to different memory block, or make a different pointer point to that memory block.
One more thing - the array of 4 chars created by malloc is not initialised - it contains garbage values.
The second example creates only one object - an array of 4 chars, called fun. (To test this, change the 4 to 40 and print out sizeof(fun)). This array lives only until the function it's declared in returns (unless it's declared outside of a function, when it lives for as long as the entire program is running). This array of 4 chars isn't initialised either.
The third example creates two objects. The first is a pointer-to-char variable called fun, just like in the first example (and as usual, it lives from the start of this function until it returns). The other object is a bit strange - it's an array of 4 chars, initialised to { 'f', 'u', 'n', 0 }, which has no name and that lives for as long as the entire program is running. It's also not guaranteed to be modifiable (although what happens if you try to modify it is left entirely undefined - it might crash your program, or it might not). The variable fun is initialised with the location of this strange unnamed, unmodifiable, long-lived array (but just like in the first example, this association isn't permanent - you can make fun point to something else).
The reason why there's so many confusing similarities and differences between arrays and pointers is down to two things:
The "array syntax" in C (the [] operator) actually works on pointers, not arrays!
Trying to pin down an array is a bit like catching fog - in almost all cases the array evaporates and is replaced by a pointer to its first element instead.

Resizing a char[x] to char[y] at runtime

OK, I hope I explain this one correctly.
I have a struct:
typedef struct _MyData
{
char Data[256];
int Index;
} MyData;
Now, I run into a problem. Most of the time MyData.Data is OK with 256, but in some cases I need to expand the amount of chars it can hold to different sizes.
I can't use a pointer.
Is there any way to resize Data at run time? How?
Code is appreciated.
EDIT 1:
While I am very thankful for all the comments, the "maybe try this..." or "do that", or "what you are dong is wrong..." comments are not helping. Code is the help here. Please, if you know the answer post the code.
Please note that:
I cannot use pointers. Please don't try to figure out why, I just can't.
The struct is being injected into another program's memory that's why no pointers can be used.
Sorry for being a bit rough here but I asked the question here because I already tried all the different approaches that thought might work.
Again, I am looking for code. At this point I am not interested in "might work..." or " have you considered this..."
Thank you and my apologies again.
EDIT 2
Why was this set as answered?
You can use a flexible array member
typedef struct _MyData
{
int Index;
char Data[];
} MyData;
So that you can then allocate the right amount of space
MyData *d = malloc(sizeof *d + sizeof(char[100]));
d->Data[0..99] = ...;
Later, you can free, and allocate another chunk of memory and make a pointer to MyData point to it, at which time you will have more / less elements in the flexible array member (realloc). Note that you will have to save the length somewhere, too.
In Pre-C99 times, there isn't a flexible array member: char Data[] is simply regarded as an array with incomplete type, and the compiler would moan about that. Here i recommend you two possible ways out there
Using a pointer: char *Data and make it point to the allocated memory. This won't be as convenient as using the embedded array, because you will possibly need to have two allocations: One for the struct, and one for the memory pointed to by the pointer. You can also have the struct allocated on the stack instead, if the situation in your program allows this.
Using a char Data[1] instead, but treat it as if it were bigger, so that it overlays the whole allocated object. This is formally undefined behavior, but is a common technique, so it's probably safe to use with your compiler.
The problem here is your statement "I can't use a pointer". You will have to, and it will make everything much easier. Hey, realloc even copies your existing data, what do you want more?
So why do you think you can't use a pointer? Better try to fix that.
You would re-arrange the structure like that
typedef struct _MyData
{
int Index;
char Data[256];
} MyData;
And allocate instances with malloc/realloc like that:
my_data = (MyData*) malloc ( sizeof(MyData) + extra_space_needed );
This is an ugly approach and I would not recommend it (I would use pointers), but is an answer to your question how to do it without a pointer.
A limitation is that it allows for only one variable size member per struct, and has to be at the end.
Let me sum up two important points I see in this thread:
The structure is used to interact between two programs through some IPC mechanism
The destination program cannot be changed
You cannot therefore change that structure in any way, because the destination program is stuck trying to read it as currently defined. I'm afraid you are stuck.
You can try to find ways to get the equivalent behavior, or find some evil hack to force the destination program to read a new structure (e.g., modifying the binary offsets in the executable). That's all pretty application specific so I can't give much better guidance than that.
You might consider writing a third program to act as an interface between the two. It can take the "long" messages and do something with them, and pass the "short" messages onward to the old program. You can inject that in between the IPC mechanisms fairly easily.
You may be able to do this like this, without allocating a pointer for the array:
typedef struct _MyData
{
int Index;
char Data[1];
} MyData;
Later, you allocate like this:
int bcount = 256;
MyData *foo;
foo = (MyData *)malloc(sizeof(*foo) + bcount);
realloc:
int newbcount = 512;
MyData *resized_foo;
resized_foo = realloc((void *)foo, sizeof(*foo) + newbcount);
It looks like from what you're saying that you definitely have to keep MyData as a static block of data. In which case I think the only option open to you is to somehow (optionally) chain these data structures together in a way that can be re-assembled be the other process.
You'd need and additional member in MyData, eg.
typedef struct _MyData
{
int Sequence;
char Data[256];
int Index;
} MyData;
Where Sequence identifies the descending sequence in which to re-assemble the data (a sequence number of zero would indicate the final data buffer).
The problem is in the way you're putting the question. Don't think about C semantics: instead, think like a hacker. Explain exactly how you are currently getting your data into the other process at the right time, and also how the other program knows where the data begins and ends. Is the other program expecting a null-terminated string? If you declare your struct with a char[300] does the other program crash?
You see, when you say "passing data" to the other program, you might be [a] tricking the other process into copying what you put in front of it, [b] tricking the other program into letting you overwrite its normally 'private' memory, or [c] some other approach. No matter which is the case, if the other program can take your larger data, there is a way to get it to them.
I find KIV's trick quite usable. Though, I would suggest investigating the pointer issue first.
If you look at the malloc implementations
(check this IBM article, Listing 5: Pseudo-code for the main allocator),
When you allocate, the memory manager allocates a control header and
then free space following it based on your requested size.
This is very much like saying,
typedef struct _MyData
{
int size;
char Data[1]; // we are going to break the array-bound up-to size length
} MyData;
Now, your problem is,
How do you pass such a (mis-sized?) structure to this other process?
That brings us the the question,
How does the other process figure out the size of this data?
I would expect a length field as part of the communication.
If you have all that, whats wrong with passing a pointer to the other process?
Will the other process identify the difference between a pointer to a
structure and that to a allocated memory?
You cant reacolate manualy.
You can do some tricks wich i was uning when i was working aon simple data holding sistem. (very simple filesystem).
typedef struct
{
int index ;
char x[250];
} data_ztorage_250_char;
typedef struct
{
int index;
char x[1000];
} data_ztorage_1000_char;
int main(void)
{
char just_raw_data[sizeof(data_ztorage_1000_char)];
data_ztorage_1000_char* big_struct;
data_ztorage_250_char* small_struct;
big_struct = (data_ztorage_1000_char*)big_struct; //now you have bigg struct
// notice that upper line is same as writing
// big_struct = (data_ztorage_1000_char*)(&just_raw_data[0]);
small_struct = (data_ztorage_250_char*)just_raw_data;//now you have small struct
//both structs starts at same locations and they share same memory
//addresing data is
small_struct -> index = 250;
}
You don't state what the Index value is for.
As I understand it you are passing data to another program using the structure shown.
Is there a reason why you can't break your data to send into chunks of 256bytes and then set the index value accordingly? e.g.
Data is 512 bytes so you send one struct with the first 256 bytes and index=0, then another with the next 256 bytes in your array and Index=1.
How about a really, really simple solution? Could you do:
typedef struct _MyData
{
char Data[1024];
int Index;
} MyData;
I have a feeling I know your response will be "No, because the other program I don't have control over expects 256 bytes"... And if that is indeed your answer to my answer, then my answer becomes: this is impossible.

Resources