Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Need Help Declaring a Pointer to an Array of Structures

Reply
Thread Tools

Need Help Declaring a Pointer to an Array of Structures

 
 
gcary@trancer.com
Guest
Posts: n/a
 
      08-10-2006
I am having trouble figuring out how to declare a pointer to an array
of structures and initializing the pointer with a value. I've looked
at older posts in this group, and tried a solution that looked
sensible, but it didn't work right. Here is a simple example of what
I'm trying to accomplish:

// I have a hardware peripheral that I'm trying to access
// that has two ports. Each port has 10 sequential
// registers. Create a structure definition that
// defines a single port.

typedef struct {
long long1;
long long2;
long long3;
long long4;
long long5;
long long6;
long long7;
long long8;
long long9;
long long10;
} volatile my_struct;

// Create a pointer to an array of two structures
my_struct (*my_struct_ptr)[2];

#define PERIPHERAL_BASEADDR 0xA0000000

int main(int argc, char **argv)
{
// This is the syntax I came up with to initialize
// the pointer. Keep in mind that this line of code
// isn't even needed in this example to illustrate the
// behavior of the compiler with respect to addressing.
my_struct_ptr = (my_struct (*)[])PERIPHERAL_BASEADDR;

printf("&my_struct_ptr[0] = %08X\n",
&my_struct_ptr[0]);

printf("&my_struct_ptr[1] = %08X\n",
&my_struct_ptr[1]);

printf("sizeof(my_struct) = %x\n",
sizeof(my_struct));

printf("sizeof(my_struct_ptr[0]) = %x\n",
sizeof(my_struct_ptr[0]));

printf("sizeof(my_struct_ptr[1]) = %x\n",
sizeof(my_struct_ptr[1]));

printf("&(my_struct_ptr[0]->long1) = %08X\n",
&(my_struct_ptr[0]->long1));

printf("&(my_struct_ptr[0]->long10) = %08X\n",
&(my_struct_ptr[0]->long10));

printf("&(my_struct_ptr[1]->long1) = %08X\n",
&(my_struct_ptr[1]->long1));

printf("&(my_struct_ptr[1]->long10) = %08X\n",
&(my_struct_ptr[1]->long10));
}

Here is the output of the program:

&my_struct_ptr[0] = A0000000
&my_struct_ptr[1] = A0000050
sizeof(my_struct) = 28
sizeof(my_struct_ptr[0]) = 50
sizeof(my_struct_ptr[1]) = 50
&(my_struct_ptr[0]->long1) = A0000000
&(my_struct_ptr[0]->long10) = A0000024
&(my_struct_ptr[1]->long1) = A0000050
&(my_struct_ptr[1]->long10) = A0000074

It correctly calculates the size of the typedef'd structure, but it
reports the size of each element of the array as twice as big as it
should be. If there are three elements in the array, then the size of
each element is 3 times as big. In this example, long1 of the second
element should be at address A0000028.

I am using the GCC compiler, but I don't think it is a bug in the
compiler. I tried it in Visual C++ and got the same results.

I tried to use a pointer to a single structure and use it like an
array. That only half works because the compiler doesn't see it as an
array of structures and therefore you can't access the elements of the
structure and index as well.

Any help would be appreciated.

Thanks,

Greg

 
Reply With Quote
 
 
 
 
Chris Torek
Guest
Posts: n/a
 
      08-11-2006
In article < .com>
<> wrote:
>typedef struct { ... } volatile my_struct;


In general, I advise against making nameless structure types and
then giving them aliases. I suggest even more caution when mixing
"volatile" in. See <http://web.torek.net/torek/c/types2.html>.
(Neither of these is the problem though.)

>// Create a pointer to an array of two structures
>my_struct (*my_struct_ptr)[2];


[rest of code snipped]

You declare a "pointer to an array" here, just as your comment
implies; but you do not *want* a "pointer to an array", you want
a "pointer to an element". This is because a "pointer to T", for
some type T, often -- perhaps even "usually", and certainly in
your case -- points to the first of many elements of type "T" that
are in an array. A "pointer to array N of T" points to the first
array in an array of many arrays. In this case, you are making
the pointer point to the first "array 2 of T", so that p[i] is
the i'th "array 2 of T". See <http://web.torek.net/torek/c/pa.html>.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
 
Reply With Quote
 
 
 
 
gcary@trancer.com
Guest
Posts: n/a
 
      08-11-2006
Chris Torek wrote:
> In article < .com>
> <> wrote:
> >typedef struct { ... } volatile my_struct;

>
> In general, I advise against making nameless structure types and
> then giving them aliases. I suggest even more caution when mixing
> "volatile" in. See <http://web.torek.net/torek/c/types2.html>.
> (Neither of these is the problem though.)


Chris, thanks for your help. Thanks for your advice about nameless
structure types. That makes some sense. I'll re-read your website
tomorrow when I'm more awake. About the volatile modifier, would you
recommend placing it on each of the elements of the structure rather
than the structure itself?

>
> >// Create a pointer to an array of two structures
> >my_struct (*my_struct_ptr)[2];

>
> [rest of code snipped]
>
> You declare a "pointer to an array" here, just as your comment
> implies; but you do not *want* a "pointer to an array", you want
> a "pointer to an element". This is because a "pointer to T", for
> some type T, often -- perhaps even "usually", and certainly in
> your case -- points to the first of many elements of type "T" that
> are in an array. A "pointer to array N of T" points to the first
> array in an array of many arrays. In this case, you are making
> the pointer point to the first "array 2 of T", so that p[i] is
> the i'th "array 2 of T". See <http://web.torek.net/torek/c/pa.html>.


I understand what you're saying. I'll give it a shot tomorrow when I'm
back at work. I think you're saying that what I need to do is the
following:

my_struct (*mystruct_ptr)[1];

Then just treat the pointer as any other pointer. Like I said before,
I'll re-read your web pages tomorrow and hopefully get even more out of
it.

Thanks again for your help,

Greg

 
Reply With Quote
 
Barry Schwarz
Guest
Posts: n/a
 
      08-11-2006
On 10 Aug 2006 16:16:04 -0700, wrote:

>I am having trouble figuring out how to declare a pointer to an array
>of structures and initializing the pointer with a value. I've looked


Clarify your terminology. The phrase pointer to an array is
frequently misused to mean pointer to the first element of the array.
For a type T, this would be coded as T *ptr. To be technically
correct, a pointer to an array of type T would be coded as T (*ptr)[N]
where N would be a self-defining value (compile time constant). Which
do you really want?

Your following code deals with the second type. However, since the
first type allows you to step through the array more easily (less
typing), the second type is much less frequently used.

>at older posts in this group, and tried a solution that looked
>sensible, but it didn't work right. Here is a simple example of what
>I'm trying to accomplish:
>
>// I have a hardware peripheral that I'm trying to access
>// that has two ports. Each port has 10 sequential
>// registers. Create a structure definition that
>// defines a single port.
>
>typedef struct {
> long long1;
> long long2;
> long long3;
> long long4;
> long long5;
> long long6;
> long long7;
> long long8;
> long long9;
> long long10;
>} volatile my_struct;


Doesn't the volatile need to be between the words typedef and struct
on the first line of the declaration?

>
>// Create a pointer to an array of two structures
>my_struct (*my_struct_ptr)[2];


This does define a pointer to an array of 2 struct.

>
>#define PERIPHERAL_BASEADDR 0xA0000000
>
>int main(int argc, char **argv)
>{
> // This is the syntax I came up with to initialize
> // the pointer. Keep in mind that this line of code
> // isn't even needed in this example to illustrate the
> // behavior of the compiler with respect to addressing.
> my_struct_ptr = (my_struct (*)[])PERIPHERAL_BASEADDR;


If you change the subscript from [] to [2] it should be syntactically
correct.

>
> printf("&my_struct_ptr[0] = %08X\n",
> &my_struct_ptr[0]);


Here you promise the argument corresponding to %X will have type int.
You actually pass the an argument that has type pointer to array of 2
struct. (The & and the [0] basically cancel each other.) This
invokes undefined behavior. If you want to print the value of a
pointer, use %p and cast the value to a void*.

>
> printf("&my_struct_ptr[1] = %08X\n",
> &my_struct_ptr[1]);
>
> printf("sizeof(my_struct) = %x\n",
> sizeof(my_struct));


sizeof evaluates to a size_t which need not be an int. Cast it if you
want to use %x.

>
> printf("sizeof(my_struct_ptr[0]) = %x\n",
> sizeof(my_struct_ptr[0]));
>
> printf("sizeof(my_struct_ptr[1]) = %x\n",
> sizeof(my_struct_ptr[1]));
>
> printf("&(my_struct_ptr[0]->long1) = %08X\n",
> &(my_struct_ptr[0]->long1));
>
> printf("&(my_struct_ptr[0]->long10) = %08X\n",
> &(my_struct_ptr[0]->long10));
>
> printf("&(my_struct_ptr[1]->long1) = %08X\n",
> &(my_struct_ptr[1]->long1));
>
> printf("&(my_struct_ptr[1]->long10) = %08X\n",
> &(my_struct_ptr[1]->long10));
>}
>
>Here is the output of the program:
>
>&my_struct_ptr[0] = A0000000
>&my_struct_ptr[1] = A0000050
>sizeof(my_struct) = 28
>sizeof(my_struct_ptr[0]) = 50
>sizeof(my_struct_ptr[1]) = 50
>&(my_struct_ptr[0]->long1) = A0000000
>&(my_struct_ptr[0]->long10) = A0000024
>&(my_struct_ptr[1]->long1) = A0000050
>&(my_struct_ptr[1]->long10) = A0000074
>
>It correctly calculates the size of the typedef'd structure, but it
>reports the size of each element of the array as twice as big as it


No it doesn't. my_struct has a size of 40 bytes (hex 2.
my_struct_ptr is a pointer to an array of 2 struct. my_struct_ptr[0]
is the array it points to. Since the array has two elements, the size
of the array is 80 bytes (hex 50). Hence the question I asked at the
beginning. You want the pointer to point to an element of the array,
not the array itself.

>should be. If there are three elements in the array, then the size of
>each element is 3 times as big. In this example, long1 of the second


You never asked for the size of an element of the array. To do so you
would have to code my_struct_ptr[0][0].

>element should be at address A0000028.


It is. You never asked for the address of that variable. The name
for that variable is my_struct_ptr[0][1].long1. Put an & in front to
get its address.

Your code - &(my_struct_ptr[1]->long1) - evaluates as follows:

my_struct_ptr is a pointer to an array of struct
my_struct_ptr[1] is the second array it points (the next array
past the first)
my_struct_ptr[1] is an array expression. As usual (when not the
operand of sizeof or &), the array expression evaluates to the address
of the first element of the array with type pointer to element. Since
the array is an array of struct, this evaluates to the address of the
first struct of the second array or &my_struct_ptr[1][0] with type
pointer to struct.
my_struct_ptr[1]->long1 is the first element of this struct which
is actually the third struct starting at your special address. The
first struct is my_struct_ptr[0][0], the second is [0][1], and [1][0]
is the third.

>
>I am using the GCC compiler, but I don't think it is a bug in the
>compiler. I tried it in Visual C++ and got the same results.


The "problem" is you chose to use a pointer to array rather than
pointer to first element of array.

>
>I tried to use a pointer to a single structure and use it like an
>array. That only half works because the compiler doesn't see it as an
>array of structures and therefore you can't access the elements of the
>structure and index as well.


Yes it can. Show your code so we can see what you did wrong.


Remove del for email
 
Reply With Quote
 
Rod Pemberton
Guest
Posts: n/a
 
      08-11-2006

"Chris Torek" <> wrote in message
news:...
> In article < .com>
> <> wrote:
> >typedef struct { ... } volatile my_struct;

>
> In general, I advise against making nameless structure types and
> then giving them aliases. I suggest even more caution when mixing
> "volatile" in. See <http://web.torek.net/torek/c/types2.html>.


CT:"[insert link to scopes and linkage rules once I write the html page]"

That would be nice.


CT:"One of the biggest drawbacks I find with C's typedef syntax is that it
mucks[sic] up C's declarations (and C's 'declaration mirrors use' syntax is
already one of C's most confusing features)."

Really?


CT:"With typedef names, however, we see only an ordinary identifier,
indistinguishable from any other ordinary identifier, ..."

(warning: sarcasm) What? You don't like the implicit "typedefname" keyword?
Isn't it the best feature of C? Ah, for want of two keywords, C isn't
LALR(1)...


CT:"...this (C89-specific) code fragment: 'void f(x);' Can you tell from
this code fragment whether x is a typedef name, or a variable name whose
type is defaulted to int?"

Implicit int versus type-specifier problem: C89, no. (But, C99, yes.)


CT:"For this reason, those who use typedefs almost invariably invent a
typographic convention (or several conventions) to make them stand out. If
we can tell at a glance that some identifier is a typedef-alias, the
syntactic problem vanishes. In my experince[sic], the three most common
conventions are:"

(spelling error)

CT(1):"Appending _t to the name, producing identifiers like uid_t,
pthread_t, and so on. (The T here stands for 'type'. Note that POSIX
reserves all such identifiers.)"

Never heard of that...

CT(2):"Using an initial capital letter for the identifier (provided, of
course, that initial capitals are never used for other purposes)."

Never heard of that... Oh, wait: Pascal programmers meet C...

CT(3):"Spelling the name in all-capitals, like Standard C's FILE type."

Seen that, and I don't really like it, except for FILE.


CT:"While I personally dislike typedef and am entirely willing to write out
the struct keyword every time,..."

Okay, _IF_ it existed, would you be willing to write out "typedefname"
everytime? How about this (using your examples):

#define typedefname ut
typedef int x;
int *a;
ut x *b; /* typedefname x *b */
int **p = &b;

void f(x); /* int x */
void f(ut x); /* typedefname x */

Wow, look at that... It's even portable:
#define ut

Now just add a keyword for terminated if and you've got LALR(1) C. In fact,
I'm injecting an implicit token where "ut" or "typedefname" is with
bison/flex grammars (one grammar rule change), and it _seems_ to be working
quite well... Determining where to inject was a bit difficult though. I'm
not sure if it's 100% accurate yet. I was trying to avoid passing
information from bison to flex.

CT:"Suppose we rewrite the earlier code fragment to use a typedef-name to
alias the incomplete structure type, and then use the alias in the function
prototypes: ... While the actual type-declaration still happens because of
the struct keyword, we now get a compiler diagnostic for the third line,
because the misspelled identifier is not a typedef-name"

Nifty.


CT:"...that it is the typedef keyword that defines the types, and attempt to
omit the structure tags, giving something like: ... which of course does not
work at all"

Confusing... Okay, when you said "attempt to omit the structure tags" you
were referring to the inner elements of the last two structures, not the
typedef-names for the last two structures. Dude, you named _everything_ the
same... including the stuff you weren't trying to point out as problematic.


CT:"Note that if you do use typedefs, and you avoid the situation I describe
as a 'bad idea' -- that is, you always avoid defining an inner-scope type
with the same name as some outer-scope type..."

Clarification is good, but three or four sentences late.



Rod Pemberton


 
Reply With Quote
 
Al Balmer
Guest
Posts: n/a
 
      08-11-2006
On Fri, 11 Aug 2006 03:19:54 -0400, "Rod Pemberton"
<> wrote:

>CT(1):"Appending _t to the name, producing identifiers like uid_t,
>pthread_t, and so on. (The T here stands for 'type'. Note that POSIX
>reserves all such identifiers.)"
>
>Never heard of that...


Never heard of the convention, or never heard of the reservation? I've
seen the convention used for years. And it is a POSIX.1 reserved
namespace, "_t" as a suffix, in any context. I don't have the actual
standard handy, but it's in table 2-8 of Gallmeister,
"POSIX.4rogramming for the Real World".

--
Al Balmer
Sun City, AZ
 
Reply With Quote
 
gcary@trancer.com
Guest
Posts: n/a
 
      08-11-2006
Barry Schwarz wrote:
> On 10 Aug 2006 16:16:04 -0700, wrote:
>
> >I am having trouble figuring out how to declare a pointer to an array
> >of structures and initializing the pointer with a value. I've looked

>
> Clarify your terminology. The phrase pointer to an array is
> frequently misused to mean pointer to the first element of the array.
> For a type T, this would be coded as T *ptr. To be technically
> correct, a pointer to an array of type T would be coded as T (*ptr)[N]
> where N would be a self-defining value (compile time constant). Which
> do you really want?


I do not believe T *ptr will work when trying to access the elements of
the structure if I use a syntax such as this: ptr[1]->long2;
So what I want is T (*ptr)[1], which will allow the type of syntax I
desire.

> Doesn't the volatile need to be between the words typedef and struct
> on the first line of the declaration?


Good point, I don't know the answer. What you say seems reasonable.
Since not all of the registers are actually volatile, maybe I should
place the volatile keyword only on those structure members that are
volatile.

> Here you promise the argument corresponding to %X will have type int.
> You actually pass the an argument that has type pointer to array of 2
> struct. (The & and the [0] basically cancel each other.) This
> invokes undefined behavior. If you want to print the value of a
> pointer, use %p and cast the value to a void*.


I agree that it was sloppy and I should have cast it to something. I
didn't know about %p. I tried it on our system and it is unsupported.
It is a really simplified version of printf, so I'm not surprised.

> >I tried to use a pointer to a single structure and use it like an
> >array. That only half works because the compiler doesn't see it as an
> >array of structures and therefore you can't access the elements of the
> >structure and index as well.

>
> Yes it can. Show your code so we can see what you did wrong.


What I said was I used a pointer to a single structure, not a structure
that has anything to do with an array.

typedef struct {
long long1;
long long2;
} my_struct;

my_struct *my_struct_ptr;

#define PERIPHERAL_BASEADDR 0xA0000000

int main(int argc, char **argv)
{
my_struct_ptr = (my_struct *)PERIPHERAL_BASEADDR;

xil_printf("&(my_struct_ptr[0]->long1) = %08X\r\n",
&(my_struct_ptr[0]->long1));
}

compiler output:
error: invalid type argument of `->'

Thanks for your help as well as everyone else. I've figured out the
syntax I need to accomplish what I need.

Regards,

Greg

 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      08-11-2006
writes:
> Barry Schwarz wrote:
>> On 10 Aug 2006 16:16:04 -0700, wrote:
>>
>> >I am having trouble figuring out how to declare a pointer to an array
>> >of structures and initializing the pointer with a value. I've looked

>>
>> Clarify your terminology. The phrase pointer to an array is
>> frequently misused to mean pointer to the first element of the array.
>> For a type T, this would be coded as T *ptr. To be technically
>> correct, a pointer to an array of type T would be coded as T (*ptr)[N]
>> where N would be a self-defining value (compile time constant). Which
>> do you really want?

>
> I do not believe T *ptr will work when trying to access the elements of
> the structure if I use a syntax such as this: ptr[1]->long2;
> So what I want is T (*ptr)[1], which will allow the type of syntax I
> desire.


No, you almost certainly want a pointer to an element of the array.
Just use "." rather than "->", since ptr[1] is a structure, not a
pointer:

#include <stdio.h>
int main(void)
{
typedef struct {
long long1;
long long2;
} T;
T arr[2] = { { 10, 20 },
{ 30, 40 } };
T *ptr = arr;
printf("ptr[1]->long2 = %ld\n", ptr[1].long2);
return 0;
}

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
gcary@trancer.com
Guest
Posts: n/a
 
      08-11-2006
Keith Thompson wrote:
> No, you almost certainly want a pointer to an element of the array.
> Just use "." rather than "->", since ptr[1] is a structure, not a
> pointer:
>
> #include <stdio.h>
> int main(void)
> {
> typedef struct {
> long long1;
> long long2;
> } T;
> T arr[2] = { { 10, 20 },
> { 30, 40 } };
> T *ptr = arr;
> printf("ptr[1]->long2 = %ld\n", ptr[1].long2);
> return 0;
> }


You're right. Since I needed to create a pointer to an array of
structures, I led myself to believe I needed to use the "->" notation.

Thanks to everyone who got me set straight about what I was doing. I
guess there are at least two ways to skin this cat, but I think this
one is the simpler and more straightforward approach. Not as
mindbending.

Greg

 
Reply With Quote
 
Joe Wright
Guest
Posts: n/a
 
      08-12-2006
wrote:
> Chris Torek wrote:
>> In article < .com>
>> <> wrote:
>>> typedef struct { ... } volatile my_struct;

>> In general, I advise against making nameless structure types and
>> then giving them aliases. I suggest even more caution when mixing
>> "volatile" in. See <http://web.torek.net/torek/c/types2.html>.
>> (Neither of these is the problem though.)

>
> Chris, thanks for your help. Thanks for your advice about nameless
> structure types. That makes some sense. I'll re-read your website
> tomorrow when I'm more awake. About the volatile modifier, would you
> recommend placing it on each of the elements of the structure rather
> than the structure itself?
>


Please, what is your need for volatile? Is the structure and/or its
members changeable by things outside your program?

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
pointer to an array vs pointer to pointer subramanian100in@yahoo.com, India C Programming 5 09-23-2011 10:28 AM
structures, structures and more structures (questions about nestedstructures) Alfonso Morra C Programming 11 09-24-2005 07:42 PM
declaring a function that returns a pointer to 1-d array junky_fellow@yahoo.co.in C Programming 12 09-17-2005 08:57 PM
declaring an array with "new Array()" vs "[]" sonic Javascript 5 07-12-2005 03:45 PM
Array of pointer Vs Pointer to Array sangeetha C Programming 9 10-09-2004 07:01 PM



Advertisments