English 中文(简体)
Problems with structures with pointers to arrays of other structures in C
原标题:

I am attempting to tackle college worksheet on C programming (no marking for it, just to improve our learning). What we re meant to do is get a few details about shipping docks. I decided to use structures for this.

My code is below, what I need help with is to print out the information (to see if its working) of whats at the location of the shipyards .run.

Everything compiles and according to the debugger shipyard1.run and shipyard2.run point to different locations, but I can not see the values.

int main(int argc, char** argv)
{
    typedef struct dockInfo
    {
        int dockCode;
        int dockLength;
    }dckDetails;

    typdef struct shipyard
    {
        char dockName[20];

        /* however big this number is thats how many dockInfo structs are needed.*/

        int numOfDocks;             
        dckDetails *run; //points to the array of dockInfo structs

    };

    struct dockInfo *arrayD; // the array to hold all the dockInfo structs
    struct dockInfo tempo; // the temporary dockInfo struct to take in the details
    struct shipyard shipyard1;
    struct shipyard shipyard2;

    /**
    * the variables for shipyard1 and shipyard2 are then assigned
    **/

    int i;
    for (i=0;i<shipyard1.numOfDocks;i++)
    {

    arrayD=calloc(shipyard1.numOfDocks,100); // allocate a new bit of memory for arrayD
    tempo.dockCode=45*i;
    tempo.dockLength=668*i;
    arrayD[i]=tempo; //the element of arrayD becomes tempo.

    }
    shipyard1.run=arrayD; //make shipyard1.run point to the location of arrayD.

    for (i=0;i<shipyard2.numOfDocks;i++)
    {

    arrayD=calloc(shipyard2.numOfDocks,100); // allocate a new bit of memory for arrayD
    tempo.dockCode=1234*i;
    tempo.dockLength=1200*i;
    arrayD[i]=tempo; //the element of arrayD becomes tempo.

    }
    shipyard2.run=arrayD; //make shipyard2.run point to the new location of arrayD.

    int elementTest1; // need element1test to be shipyard1.run[0].dockLength;
    int elementTest2; // need element2test to be shipyard2.run[1].dockCode;

return (EXIT_SUCCESS);
}

It should be noted that I have left a lot of code out because I have yet to write it. I have used static examples for the moment (shipyard1 and shipyard2) but in the future I am going to implment a load info from file feature.

Any help would be greatly appreciated and please excuse my English if it s poor, English is not my first language.

问题回答

You have calloc() inside a for loop twice. Both times you re losing the address returned.

for () {
    addr = calloc();
    addr[i] = ...
}

the second time through the loop, the addr you got on the first time is gone (you got yourself a memory leak), the value you saved there is gone too.

Move the calloc() outside the loop ... and remember to free() the memory when you no longer need it

addr = calloc();
for () {
    addr[i] = ...
}
free(addr);

Some feedback:

  • The memory allocation parts with calloc should occur outside the loop. Now you allocate it, and then loose track of it in the next iteration because new memory is allocated and assigned.
  • memory you allocate should be freed somewhere with free
  • shipyard1.numOfDocks (same for shipyard2) is unitialized when you use it, it may be a random number (which means you have an undefined number of loop iterations, and allocate an undefined amount of memory).

Good luck!

Others have made some very good points, and you should fix your code according to them. So far, no one seems to have seen that the call to calloc() is wrong. Instead of:

arrayD=calloc(shipyard1.numOfDocks,100);

it should be:

arrayD = calloc(shipyard1.numOfDocks, sizeof *arrayD);

You want shipyard1.numOfDocks objects, each of size equal to sizeof *arrayD.

In fact, as mentioned below, you don t need to set the memory allocated to all-zeros, so you can replace calloc() by malloc():

arrayD = malloc(shipyard1.numOfDocks * sizeof *arrayD);

(Be sure to #include <stdlib.h>, whether you call calloc() or malloc().)

I have some minor comments about style:

  1. you don t need the typedef. You can write struct dockInfo instead of dckDetails. If you do keep the typedef, you should be consistent, and use the typedef name everywhere. You use struct dockInfo most of the time, and then use dckDetails once. Your usage suggests that you probably weren t comfortable declaring a pointer to the struct. However, struct dockInfo *run is a completely valid declaration.
  2. you don t need the tempo object. You can instead do: arrayD[i].dockCode = 45*i; arrayD[i].dockLength = 668*i;
  3. Unless you re running C99, you can t declare variables after statements in a block. So you should move the declarations for elementTest1 and elementTest2 to the top of main(), with other declarations.
  4. return is a statement, not a function, so the parentheses are not needed.
  5. Since you overwrite the memory allocated immediately, and don t need it to be zero, you can replace calloc() call by a suitable call to malloc().

As I said, these are minor comments. Your main problems lie with the wrong use of calloc, etc.

I shortened the variable names and re-wrote this to do what I think you are interested in. I also added display of the addresses the data is stored in. Generally, when I try to understand something in the arrays and pointers world, I make the simple case work - an embedded array (my yard1) and then do the pointer thing after that (yard2, yard3) You ll note each set of data has different start points, two add i for each point, one multiplies by i for each point.

#include <libc.h>
#include <stdlib.h>
#include <stdio.h>
#define MAX_DOCKS 100

int main(int argc, char** argv)
{

    struct dock
    {
        int code;
        int length;
    };

    struct yard
    {
        char name[20];
        int numDocks;             
        struct dock arDocks[MAX_DOCKS]; //an array of dock structs
    };

    struct yard_2 
    {
        char name[20];
        int numDocks;             
        struct dock *run; //points to the array of dock structs
    };

/* data within main function */

struct dock *arrayD; // pointer to dock structs
struct yard yard1;
struct yard_2 yard2;
struct yard_2 yard3;

int i;
char temp[] = "2 draY";
strcpy( yard2.name, temp );  /* temp is only persistant in main... */
strcpy( yard1.name, "Yard 1");  
strcpy( yard3.name, "3 y 3 a 3 r 3 d 3");
yard1.numDocks = MAX_DOCKS; /* or so I guess.. */
yard2.numDocks = MAX_DOCKS; /* or so I guess.. */
yard3.numDocks = MAX_DOCKS; /* or so I guess.. */


/* get some memory, init it to 0 */
arrayD = calloc( yard2.numDocks, sizeof( struct dock ) );
    /* connect to the yard2 struct via "run", a pointer to struct dock */
yard2.run = arrayD;    

/* without middleman... get more memory, init it to 0 */
yard3.run = calloc( yard3.numDocks, sizeof( struct dock ) );

/* at this point arrayD could be re-used to get another hunk.. */

/* fill in and display data .. */

for (i=0;i<yard1.numDocks;i++)
    {
    /* This sets  all the memory for yard 1... */
yard1.arDocks[i].code = 45 + i;
yard1.arDocks[i].length = 668 + i;

/* so here are some ways to display the data */

    printf("%d,    %d    %x   %d   %x   -   ", 
       i, yard1.arDocks[i].code, &(yard1.arDocks[i].code),
       (yard1.arDocks[i].length), &(yard1.arDocks[i].length) );

    /* This sets the memory for yard 2... */
yard2.run[i].code = 45 * i;
yard2.run[i].length = 668 * i;

/* Display through a pointer to a calloc ed array of structs is the
 same syntax as the embedded array of structs. The addresses of the 
 array are completely different - 0xbffff704 vs 0x800000  on my Intel-based iMac... */

    printf("%d    %x   %d   %x   -   ",
       yard2.run[i].code, &(yard2.run[i].code),
       yard2.run[i].length, &(yard2.run[i].length) );

yard3.run[i].code = 100 + i;
yard3.run[i].length = 2000 + i;

/* see where second calloc got its memory... */

    printf("%d    %x   %d   %x
", 
       yard3.run[i].code, &(yard3.run[i].code),
       yard3.run[i].length, &(yard3.run[i].length) );
    }

/* data all filled in, more demos of how to get it back: */

printf( "%s,     : 1
", yard1.name );
printf( "%d,     : numOfDocs 
", yard1.numDocks );
printf( "0x%x,     : arDocks 
", yard1.arDocks );


int elementTest1 = yard1.arDocks[0].length;
int elementTest2 = yard1.arDocks[1].code;
int elementTest3 = yard2.run[0].length;
int elementTest4 = yard3.run[1].code;

printf( "elementTest1:  yard1.arDocks[0].length  %d
", elementTest1 );
printf( "elementTest2:  yard1.arDocks[1].code  %d
", elementTest2 );
printf( "elementTest3:  yard2.run[0].length  %d
", elementTest3 );
printf( "elementTest4:  yard3.run[1].code;  %d
", elementTest4 );

for (i=0; i< yard2.numDocks; i++ ) {
printf("%d   %d   %d    _   ", i, yard2.run[i].length, yard2.run[i].code);
printf(" %d   %d 
",  yard3.run[i].length, yard3.run[i].code);
}


return (EXIT_SUCCESS);
}

Here s an edited example of the output, compile/build via cc, cmd line a.out:

Macintosh-6:interview Bill4$ cc

dockyard.c Macintosh-6:interview

Bill4$ a.out 

0  45  bffff6f8  668 bffff6fc - 0   800000  0   800004 -  100 800400  2000 800404 
1  46  bffff700  669 bffff704 - 45  800008  668 80000c -  101 800408  2001 80040c
2  47  bffff708  670 bffff70c - 90  800010 1336 800014 -  102 800410  2002 800414 
:
Yard 1,     : 1
100,     : numOfDocs 
0xbffff6f8,     : arDocks 
elementTest1:  yard1.arDocks[0].length  668
elementTest2:  yard1.arDocks[1].code   46
elementTest3:  yard2.run[0].length  0
elementTest4:  yard3.run[1].code;  101
 0   0   0    _    2000   100 
 1   668   45    _    2001   101 
 2   1336   90    _    2002   102 
 3   2004   135    _    2003   103  
 :
 99   66132   4455    _    2099   199 

Macintosh-6:interview Bill4$




相关问题
Fastest method for running a binary search on a file in C?

For example, let s say I want to find a particular word or number in a file. The contents are in sorted order (obviously). Since I want to run a binary search on the file, it seems like a real waste ...

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

Tips for debugging a made-for-linux application on windows?

I m trying to find the source of a bug I have found in an open-source application. I have managed to get a build up and running on my Windows machine, but I m having trouble finding the spot in the ...

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

Encoding, decoding an integer to a char array

Please note that this is not homework and i did search before starting this new thread. I got Store an int in a char array? I was looking for an answer but didn t get any satisfactory answer in the ...

热门标签