?
Solved

Accessing structure arrays within functions using pointers

Posted on 2003-02-25
18
Medium Priority
?
197 Views
Last Modified: 2010-04-15
I've got a problem with the following program:

In main() I have defined a structure array, and a pointer to this structure array.  I believe that the way it is definied is that the pointer points to the first array in the structure.

There are several functions called in main (), and I work with the structure array so I pass the functions the pointer to the structure array.  Some of these functions call other functions and I have no trouble with passing the pointer on to these other functions.

This all works fine because I am basically scanning lines of an input file and storing specific details of each line in the strucure arrays, (one array for each line of input).  After I scan a line, I increment the pointer to the structure array and it automatically points to the next array, which is great.

However, what happens when I need to alter, for instance, the 5th array in the structure within a function?  I have passed the function the pointer to the structure array, and this points to structure array[0].  I have no idea how to access specific arrays within other functions.

If the structure pointer the function works with is "struct_ptr", then to get array[1] I could just use struct_ptr++ and then access it with struct_ptr->member1, but is there any other way to do it?  I know struct_ptr[1]->member1 and struct_ptr->member1[1] are useless, but I had to try something!!  Is there a method I am missing, or an alternative solution?

Thanks in advance,

Dave
0
Comment
Question by:d_j_burton
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
18 Comments
 
LVL 6

Expert Comment

by:gj62
ID: 8020996
Do you know you need the 5th element when you call the function?  If so, why not pass &struc_ptr[4]?

The recieving function(s) can then access the members via  struct_ptr->member and not have to worry about which element in the array it is working with.
0
 

Author Comment

by:d_j_burton
ID: 8021050
Unfortunately not, each input file will be different, so the element of the structures that need to be modified will change all the time.  I may also need to modify lots of elements with one function, so passing the whole structure would be the only option.  There are ways around it and I will probably use one of them because it's going to be a better solution, but I am still curious as to whether it is possible to change the element of the structure without using the increment of the pointer.  Thanks for your comment though.
0
 
LVL 6

Expert Comment

by:gj62
ID: 8021062
BTW - you need to define your struct, but not the array (unless you want to), outside of main...

Some more explicit code:

struct testStruct {
  int x;
  char y;
};

int workWithStruct(struct testStruct * ptrToStruct)
{
  /* do something with 1 element of arrayOfStruct */
}

int main()
{
  struct testStruct arrayOfStruct[10];

  workWithStruct(&arrayOfStruct[5]);

}
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 6

Expert Comment

by:gj62
ID: 8021091
OK, then just pass the pointer to the struct array and reference it within the function - as shown:

struct testStruct {
 int x;
 char y;
};

int workWithStruct(struct testStruct aStruct[])
{
 /* do something with arrayOfStruct */
 aStruct[4].x = 7;

}

int main()
{
 struct testStruct arrayOfStruct[10];

 workWithStruct(arrayOfStruct);

}
0
 
LVL 6

Expert Comment

by:gj62
ID: 8021141
I realize I was a bit brief in my last post, and must confess I don't fully understand exactly what you are trying to do (and thinking there must be an easier way), but anyhow, the above source is passing a pointer to the array, that can be referenced just like you would within main.  Of course, you might want to pass along the number of elements that the array has, because the functions won't know...
0
 

Author Comment

by:d_j_burton
ID: 8021233
That would work fine if I was calling the one function - and you have taught me something I was unsure of!

There is a problem though....  I will try to expain a bit better (I don't have the code on hand).

main calls function filepass1 and passes it struct_ptr (pointer to structure array[0])

filepass1 uses struct_ptr and calls the functions filepass2 and structure_change1, passing the the structure pointer on to them.  So, unfortunately the functions have the pointer to the structure_array[0] and not the whole structure which is what you demonstrated above.  Does this mean I am stuffed if I want to change a specific structure array in the function structure_change1, because I can only pass it the pointer to structure_array[0]?

To be brief - is it true that I cannot change a specific element of a structure within a function that has a pointer to structure_array[0] passed to it?  Must I definitely have an alternative way of doing it?

I apologise if I'm not too clear - I've only been learning C for a few days now!
0
 

Author Comment

by:d_j_burton
ID: 8021270
That would work fine if I was calling the one function - and you have taught me something I was unsure of!

There is a problem though....  I will try to expain a bit better (I don't have the code on hand).

main calls function filepass1 and passes it struct_ptr (pointer to structure array[0])

filepass1 uses struct_ptr and calls the functions filepass2 and structure_change1, passing the the structure pointer on to them.  So, unfortunately the functions have the pointer to the structure_array[0] and not the whole structure which is what you demonstrated above.  Does this mean I am stuffed if I want to change a specific structure array in the function structure_change1, because I can only pass it the pointer to structure_array[0]?

To be brief - is it true that I cannot change a specific element of a structure within a function that has a pointer to structure_array[0] passed to it?  Must I definitely have an alternative way of doing it?

I apologise if I'm not too clear - I've only been learning C for a few days now!
0
 
LVL 6

Expert Comment

by:gj62
ID: 8021352
Don't know if I am going to answer your question or not, but I will give you my long-winded answer because I *think* I am understanding you:

First, generally you talk about elements of arrays, and members of structures.  In other words, if you have the following:

abc[4].xyz = 7;

You would say, "Set the member xyz of the 5th element (arrays are 0-based) of the abc array = 7"

OK, so...

You have a an array of structures.  You want to pass the entire array to a function so that any array element can be accessed by that function, or any other function.

In C, you don't have to do this - by passing the pointer to the array, you can still access any element in the array, and from that element access any member of that element.

If you look at the last piece of source code, you can see that in the function workWithStruct, I am accessing the 5th element of the array, and assigning the x member of the structure the value of 7.  I can keep passing the array pointer around, and dereferncing that pointer with the array notation [] to get at any individual element of the array.  Remember, each array element is a structure, and each structure has all the members of the structure that you defined.

Again, look at my example code where I say:

aStruct[4].x = 7;

This occurs in the function workWithStruct().  After I return from that function and am executing in main(), the value of

arrayOfStruct[4].x would be 7 - the function has changed the actual structure within the array!

I hope this answers it, or at least clears up some of the questions - if not, let me know and we'll try it again...
0
 
LVL 46

Expert Comment

by:Kent Olsen
ID: 8021675

Hi d j,

Part of the magic of pointers is that with just a little bit of care anything in the block pointed to can be passed anywhere, and the called routine can modify it in place.

In your case you have a table (list) of structures.  Each structure is the same size.  So you can pass the address of any structure in the table to another function.  You can also pass any element of any structure to another function.  And because you're passing the address of the actual data, the calling function can change whatever you send.  (It can't change the address, but it can change the data.)

In your case the table looks something like this:

ABCDEFG00
ABCDEFG01
ABCDEFG02
ABCDEFG03
ABCDEFG04
ABCDEFG05
ABCDEFG06
ABCDEFG07
ABCDEFG08

FunctionCall (TablePtr+4) sends the address of ABCDEFG04 to FunctionCall.  FunctionCall can then make any changes to this structure that you want, as long as the size of the structure doesn't grow.  This is a common technique that allows you to build a function that deals ONLY with the data in one struct.

If the size of any structure in the table is going to change, OR they sizes are not the same to begin with, this method won't work.  You'll have to manage an array of pointers to structures rather than an array of structures.

It sounds complicated, and your first cut or two will undoubtedly have you pressing CTL-ALT-DEL several times, but once you get the hang of it you'll never again build a unified table like you're doing now.


Good Luck,
Kdo
0
 
LVL 1

Expert Comment

by:TheBeaver
ID: 8021854
Just a few little tips here ...

struct testStruct {
int x;
char y;
} TEST_STR;

int workWithStruct(TEST_STR *aStruct) // Note pointer instead of putting a structure on the stack
{
  /* do something with arrayOfStruct */
  aStruct[4].x = 7;                  
}

int workWithStruct2(TEST_STR *pStruct) // Note pointer instead of putting a structure on the stack
{
  /* do something with pointer Of Struct */
  pStruct->x = 7;                  // Because we are dealing with pointers we use '->' instead of '.'
}


int main()
{
  TEST_STR arrayOfStruct[10];

  workWithStruct(arrayOfStruct);
  workWithStruct2(&arrayOfStruct[4]);
}


0
 

Author Comment

by:d_j_burton
ID: 8024009
Hi, I think gj62 has really answered my question as well as it could have been!  I have acccess to the code now, and I have stripped it out to give the following basic bits (I know it doesn't work!)...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct curve
{
     int    arg1;         // argument
     char   crv_lab[100]; // curve label
};

void file_pass1(FILE *, struct curve *);
void node_inp(struct curve *, char *);
void extra_opt(struct curve *);

int main(int argc, char *argv[])
{
     struct curve curve_no[200];  // Declare structure asap
     struct curve *curveptr;      // Declare structure pointer
     file_pass1(input,curveptr);  // Pass function the input file and the structure pointer
     return (0);
}

void file_pass1(FILE *input, struct curve *stptr)
{
     while (fgets(input_line,200,input))
     {
          stptr->arg1 = line_num;
          node_inp(stptr,file);          // Node function called
          extra_opt(stptr);              // Function to flag up all remaining options on line
          stptr++;                       // Increment to next structure array
     }

}

void node_inp(struct curve *stptr, char *sptr)
{
// Blah, work with each line of input
}

void extra_opt(struct curve *stptr)
{
// Here is where I was wanting to access,
// for example, element 5 of the structural array
// what would the syntax be?
}

Cheers
Dave
0
 
LVL 6

Expert Comment

by:gj62
ID: 8025517
TheBeaver,

In an array of structs, there are no differences between passing

struct *pStruct

and

struct aStruct[]

"An lvalue of type array-of-T which appears in an expression decays (with three exceptions) into a pointer to its first element; the type of the resultant pointer is pointer-to-T.

(The exceptions are when the array is the operand of a sizeof or & operator, or is a string literal initializer for a character array.)"

So your comments that:

"Note pointer instead of putting structure on stack" is not really correct - both version put a pointer on the stack - only the syntax is different - use whatever method you prefer...


0
 
LVL 6

Accepted Solution

by:
gj62 earned 75 total points
ID: 8025632
d_j_burton:

A few comments:

In main(), you have the following statements:

    struct curve curve_no[200];  // Declare structure asap
    struct curve *curveptr;      // Declare structure pointer
    file_pass1(input,curveptr);  // Pass function the input file and the structure pointer

Note the following:

*curveptr is never initialized - it is a pointer, and it is a pointer to struct curve, but it doesn't point anywhere valid yet.  You can do the following:

curveptr = curve_no;

which will point it to the first element in the curve_no array, or you could say

curveptr = &curve_no[3], which would set it equal to the 4th element (remember, they are 0-based), but the real question is, why have curveptr at all, when you can do the same thing with curve_no, and not have to worry about initialization?

You can still call file_pass1() as follows:

file_pass1(input,curve_no);  

That is legal, valid and perfectly acceptable C-syntax and will pass a pointer (not the entire structure) to file_pass1.


void extra_opt(struct curve *stptr)
{
// Here is where I was wanting to access,
// for example, element 5 of the structural array
// what would the syntax be?
}

The syntax within the function would be the same as within main() or any function:

stptr[4].arg1 = 7;

would set the arg1 member of the 5th curve structure in the array to 7...

Might I suggest that the following FAQ give much more (and better) descriptive text than I will ever be able to on this (and many other) subjects:

http://www.eskimo.com/~scs/C-faq/s6.html


0
 
LVL 6

Expert Comment

by:gj62
ID: 8025749
To beat this dead horse one more time, and offer an explicit apology to TheBeaver, I stand corrected that my statement:

"Note pointer instead of putting structure on stack" is not really correct - both version put a pointer on the stack - only the syntax is different - use whatever method you prefer...

while correct in that either version is valid syntax, is not correct in that the func(struct aStru *) is *preferred* today over func(struct aStru[]), but to the compiler there is no difference...

It used to be the other way around, because anyone reading the code would know you are passing a pointer to an array, rather than a pointer to a single struct, however, because the conversion to a pointer holds only within the formal function parameter declaration, many people now prefer to explicity pass it as a pointer, so says the gospel:  http://www.eskimo.com/~scs/C-faq/q6.4.html

Thank you...
0
 

Author Comment

by:d_j_burton
ID: 8025827
Cheers for all your help(s)!

Dave
0
 
LVL 6

Expert Comment

by:gj62
ID: 8026008
Dave,

Please read the grading guidelines - not that I really care, but why the 'B'?

A few notes regarding TheBeaver's code, to hopefully clear up confusion:

struct testStruct {
int x;
char y;
} TEST_STR;

What you have done here is to create a tag called 'testStruct' and to create an actual variable (physical memory allocated) called TEST_STR.  Perhaps you were shooting for a typedef, which are automatic in C++ (but it would be testStruct, and not TEST_STR), but not in C, and should therefor read:

typedef struct testStruct {
int x;
char y;
} TEST_STR;

You can now create variables by saying:

TEST_STR myStruct;

or,

struct testStruct myStruct;

both are legal and acceptable.  In the first instance, a casual reader WILL NOT know you are using a struct, but in the second case it is explicit.

Therefor, without the typedef you can't say

void workWithStruct(TEST_STRUCT *aStruct);

you must use

void worthWithStruct(struct testStruct * aStruct);


Next:

When to use -> vs .

When using a pointer to a struct (not an array of structs, subtle difference), you use ->.

Therefor, when you reference a specific element of an array of structs, you are not dealing with a pointer to the struct and you use .

If you have a pointer to a single struct, as TheBeaver shows with the function workWithStruct2(), you use ->

Now, look at the declarations for workWithStruct() and workWithStruct2() -

The function parameters are IDENTICAL - that is, both functions take

struct testStruct *

The difference is that in workWithStruct(), an element of an array is being accessed, and therefor members are accessible with '.'  In fact, you can't use ->, the compiler will give you an error.

In workWithStruct2(), you are using a pointer to a single struct (passed in as &arrayOfStruct[4]) and you therefor MUST use ->

Hope this helps...
0
 

Author Comment

by:d_j_burton
ID: 8026456
Cheers everyone, esp gj62.

The way I saw it, you gave me a good answer!  So I gave you the good grading.  

If I had spent more time and looked at people's profiles for grading then I would see that in fact it seems that B seems to be more of a "satisfactory" grade.  I thought your answer was good and explained things fairly well.  I appreciate the time it must have taken you to write your answers.
0
 
LVL 6

Expert Comment

by:gj62
ID: 8026634
Thanks - hope it helps!
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.
Suggested Courses
Course of the Month13 days, 23 hours left to enroll

801 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question