structures and pointers

Started by
7 comments, last by popcorn 21 years, 5 months ago
Ok where do i start? Sometimes in programming you encounter an array of pointers to a structure and while i can understand why you might do this as it is more efficient to pass pointers to functions rather than the whole array of structures I cannot see where the actual data is stored when using pointers. Look at the following source codes to see my problem the first one passes a table(an array of structures) to the functions and the second one passes an array of pointers.
  
#include <stdio.h>
#include <conio.h>
#include <string.h>

#define MAXCARS 5
#define MAXSTRING 80 //80 being the number of characters for one whole line


//structure for a car data type

typedef struct
{
  char make[MAXSTRING];
  char colour[MAXSTRING];
  int age;
}CAR;

//function prototypes

void ShowMenu(CAR cars[MAXCARS]);
void AddData(CAR cars[MAXCARS]);
void DisplayCars(CAR cars[MAXCARS]);
void DisplayOne(CAR cars[MAXCARS]);

void main(void)
{
  CAR cars[MAXCARS];
  clrscr();
  printf("size of car data structure is %d bytes\n", sizeof(CAR));
  printf("size of *cars is %d bytes\n", sizeof(CAR *));
  printf("size of array cars is %d bytes\n ", sizeof(cars));
  getch();
  ShowMenu(cars);
}

void ShowMenu(CAR cars[MAXCARS])
{
  int choice;

  clrscr();

  do
  {
    printf("Car Program\n");
    printf("1. Add Data\n");
    printf("2. Display All\n");
    printf("3. Display one\n");
    printf("4. Quit\n");
    printf("Enter choice: ");
    scanf("%d", &choice);

    switch(choice)
    {
      case 1:  AddData(cars);
	       break;
      case 2:  DisplayCars(cars);
	       break;
      case 3:  DisplayOne(cars);
               break;
      case 4:  printf("Quitting Program\n");
	       break;
      default: printf("Enter 1 to 3\n");
    }
  }
  while(choice != 4);
}

void AddData(CAR cars[MAXCARS])
{
  int i; //looping variable


  for(i=0; i<MAXCARS; i++)
  {
    printf("Enter make ");
    scanf("%s", cars[i].make);
    printf("Enter colour ");
    scanf("%s", cars[i].colour);
    printf("Enter age ");
    scanf("%d", &cars[i].age);
  }
}

void DisplayCars(CAR cars[MAXCARS])
{
  int i; //looping variable


  for(i=0; i<MAXCARS; i++)
  {
    printf("Make: %s\n", cars[i].make);
    printf("Colour: %s\n", cars[i].colour);
    printf("Age: %d\n", cars[i].age);
  }
}

void DisplayOne(CAR cars[MAXCARS])
{
  char cartofind[MAXSTRING];
  int i;

  printf("Enter car to find ");
  scanf("%s", cartofind);
  
  for(i=0; i<MAXCARS; i++)
  {
    if(strcmp(cars[i].make, cartofind) == 0)
    {
      printf("Make: %s\n", cars[i].make);
      printf("Colour: %s\n", cars[i].colour);
      printf("Age: %d\n", cars[i].age);
    }
  }
}
  

  
#include <stdio.h>
#include <conio.h>

#define MAXCARS 5
#define MAXSTRING 80 //80 being the number of characters for one whole line


//structure for a car data type

typedef struct
{
  char make[MAXSTRING];
  char colour[MAXSTRING];
  int age;
}CAR;

//function prototypes

void ShowMenu(CAR *cars[MAXCARS]);
void AddData(CAR *cars[MAXCARS]);
void DisplayCars(CAR *cars[MAXCARS]);
void DisplayOne(CAR *cars[MAXCARS]);

void main(void)
{
  CAR *cars[MAXCARS];
  clrscr();
  printf("size of car data structure is %d bytes\n", sizeof(CAR));
  printf("size of *cars is %d bytes\n", sizeof(*cars));
  printf("size of array cars is %d bytes\n ", sizeof(cars));
  getch();
  ShowMenu(cars);
}

void ShowMenu(CAR *cars[MAXCARS])
{
  int choice;

  clrscr();

  do
  {
    printf("Car Program\n");
    printf("1. Add Data\n");
    printf("2. Display All\n");
    printf("3. Display one\n");
    printf("4. Quit\n");
    printf("Enter choice: ");
    scanf("%d", &choice);

    switch(choice)
    {
      case 1:  AddData(cars);
	       break;
      case 2:  DisplayCars(cars);
	       break;
      case 3:  DisplayOne(cars);
               break;
      case 4:  printf("Quitting Program\n");
	       break;
      default: printf("Enter 1 to 3\n");
    }
  }
  while(choice != 4);
}

void AddData(CAR *cars[MAXCARS])
{
  int i; //looping variable


  for(i=0; i<MAXCARS; i++)
  {
    printf("Enter make ");
    scanf("%s", cars[i]->make);
    printf("Enter colour ");
    scanf("%s", cars[i]->colour);
    printf("Enter age ");
    scanf("%d", &cars[i]->age);
  }
}

void DisplayCars(CAR *cars[MAXCARS])
{
  int i; //looping variable


  for(i=0; i<MAXCARS; i++)
  {
    printf("Make: %s\n", cars[i]->make);
    printf("Colour: %s\n", cars[i]->colour);
    printf("Age: %d\n", cars[i]->age);
  }
}

void DisplayOne(CAR *cars[MAXCARS])
{
  char cartofind[MAXSTRING];
  int i;

  printf("Enter car to find ");
  scanf("%s", cartofind);
  
  for(i=0; i<MAXCARS; i++)
  {
    if(strcmp(cars[i]->make, cartofind) == 0)
    {
      printf("Make: %s\n", cars[i]->make);
      printf("Colour: %s\n", cars[i]->colour);
      printf("Age: %d\n", cars[i]->age);
    }
  }
}
  
as you can see, the first program passes in a table to each function and from this i can see that when you use the AddData()function each piece of data is added to the array but in the second program you pass an array of pointers so that when you have entered the data you require for the structure you only store the address for the start of this structure in the array. but what confuses me is where is all this data held in the first place. am i making a lot of sense here? How about them apples?
How about them apples?
Advertisement
with pointers, the data is stored in the memory pointed to by the pointer. that's why a pointer is called a pointer. it stores the address of a memory block in which the data actually resides. is that your question? my reading comprehension is low today.

-me

[edited by - Palidine on November 7, 2002 2:44:09 PM]
a problem that exists in the second instance of the code: nowhere is memory allocated for the structures that the cars array's pointers point to.

you need to do something like:


  cars *[numCars];for (int i = 0; i < numCars; i++)    cars[i] = 0; //or = NULL; depending on your preference    


then in your addData routine:

  for(i = 0; i < MAXCARS; i++){    if (cars[i] == 0)        cars[i] = new CAR();    //then do your normal load data stuffs}    


no makey sense? time to reread that pointers chapter..

-me

[edited by - Palidine on November 7, 2002 2:52:52 PM]
The cars data in the second example isn't going to exist in memory. All you've declared is an array of pointers to structures, you haven't declared the structures themselves. Run this in windows and you'll get an access violation exception because you'll be trying to set variables which don't exist in memory. If you are going to use an array of pointers they need to be dynamically allocated with new. The first example is fine because you declared the structures.

CARS cars[100]; // array of structures
CARS *pCars[100] // array of pointers to structures

// create the pCars structures in memory
for (int i=0; i<100; i++)
pCars = new CARS; // allocate space for structure

(That pCars variable in the loop is supposed to be indexed but
it keeps missing it out when I post)

The array of structures will occupy 100*sizeof(CARS)
the array of pointers on their own will occupy 400 bytes since a pointer is 4 bytes long

[edited by - philscott on November 7, 2002 3:11:01 PM]


[edited by - philscott on November 7, 2002 3:13:11 PM]
Yeah i think you are right Palidine. you see what confused me at first was what you pointed out in your second post about not declaring memory for my structures. the code actually works though and i can only guess that the compiler was actually declaring memory for the structures and initialising them.

oh yeah in your second post don''t you mean to write

if (cars == 0)
cars = new CAR;<br><br>rather than <br>if (cars == 0) <br> cars = new CAR(); </i> <br><br> How about them apples?
How about them apples?
no, i meant what i said. cars will never be == 0 b/c you declared it as a variable. in the loop of my definition i set all pointers in the CARS array to 0 to indicate that no memory had yet been allocated. the reason i make the check if cars == 0 is b/c you may want to be calling that function multiple times for the same array of cars. i.e. go back and reenter data b/c it''s changed. the if == 0 check just makes sure you don''t double allocate memory for a structure that already exists. that''ll make for a bigass memory leak

also, you currently have a memory leak b/c you never delete the cars anywhere

do this at the end of the program:


  for (int i = 0; i < numCars; i++)    delete cars[i];  
OK i think i''ve got it now.

so when you using an array of pointers to a structure you have to allocate memory for the structure first and then free the memory after you''ve finished with it.

However i wonder why the second source code still works on my computer. i used turbo c++ version 3 to create the programs and i have windows xp installed on my pc. any ideas?

thanks ppl

How about them apples?
How about them apples?
If Turbo C is compiling a DOS program then the computer doesn't automatically check for access violations. If you were to try and compile this for a windows platform and run it then it will crash. You can get away with it in DOS even if you are running it in windows with the DOS dialog box but it won't be reliable. All the pointers you declare in the second program are uninitialised so you have no idea what they are pointing at. The code:

CAR *car;
strcpy(car->make, string);

Is overwriting an unknown area of memory because car is uninitialised and no structure has been allocated. But:

CAR *car = new CAR;

creates a new structure in free memory and initialises the car pointer to point at it. It is now safe to fill the data structure using this pointer.

[edited by - philscott on November 8, 2002 5:10:16 AM]
thanks for the reply philscott.
You were right, the program doesn't work in windows
How about them apples?

[edited by - popcorn on November 8, 2002 9:54:00 PM]
How about them apples?

This topic is closed to new replies.

Advertisement