1

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?

Community
  • 1
  • 1
ash9209
  • 1,018
  • 2
  • 9
  • 16

3 Answers3

2

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

enter image description here

Your student array from main looks like:

enter image description here

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

Mihai Maruseac
  • 20,967
  • 7
  • 57
  • 109
  • I think you misunderstood it a bit. I'm not referring to my **name** character array at all. And do you know the solution to my problem? (The array variable inside an array of structure. – ash9209 Aug 11 '13 at 14:00
  • Perfect visualization @MihaiMaruseac. Brilliant. – ash9209 Aug 11 '13 at 14:26
1

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.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • Understood it perfectly. – ash9209 Aug 11 '13 at 14:05
  • Oh by the way, I remembered when you used **strcpy** that we cannot allocate a string to a character array directly like **str = "Yu Hao";** Is the alternative solution like this? : ***str = "Yu Hao";** – ash9209 Aug 11 '13 at 14:09
  • No, there isn't. Also, using `strcpy` is prone to disaster. Think about `strcpy(student[0].name, "A very large string which cleary doesn't fit into the name[10] array")` – Mihai Maruseac Aug 11 '13 at 14:12
  • @MihaiMaruseac That's not what is asked here, in case that is, just use `strncpy` instead. – Yu Hao Aug 11 '13 at 14:14
  • It was only a suggestion that it is a bad practice to use unchecked string operations. – Mihai Maruseac Aug 11 '13 at 14:17
  • @ash9209 No, you can't assign a string literal directly like that. You can initialize like `char name[] = "Yu Hao";` but your `char` array is in a `struct`. – Yu Hao Aug 11 '13 at 14:17
  • @MihaiMaruseac It is a good practice, I'll add it to the answer. – Yu Hao Aug 11 '13 at 14:18
0

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.

Summer_More_More_Tea
  • 12,740
  • 12
  • 51
  • 83
  • Could you elaborate on the **malloc(25)** part? You said **you can also specify 40 or 50 to meet your requirement**. We need to store 10 addresses in **inputs**. Fine, I get that. I still don't understand how 25 comes in the picture. Where my thinking is leading me, it is allocating 25 bytes to each address in the **inputs** array. Correct? if not, where am I going wrong? – ash9209 Aug 11 '13 at 14:13
  • @ash9209 OK. A pointer is a memory address as I said. It is an address to the underlying memory storage. While we know, like array, to read a chunk of memory we not only need to know its beginning address, also its size (or we'll run out the memory and access to invalid address, I bet you know that when accessing array we should not acess the elments out of the boundary :p). Here is it. The 20, 40, even 50 is the memory size you want to *use* in byte. The actual size is decided by you yourself. If you want a 50-byte memory chunk, np, `malloc(50)` even a 5000-byte one `malloc(5000)`. – Summer_More_More_Tea Aug 11 '13 at 14:19
  • Alright, this was much better. Got it perfectly. Appreciate you giving me your valuable time. Cheers. – ash9209 Aug 11 '13 at 14:24