What type is a structure?

  • Thread starter damian birchler
  • Start date
D

damian birchler

Hi
I'm wondering of what type a structure is. Of course, it is a
_structure_, but an array isn't an _array_ either. So of what type is
a structure? I'd say a pointer, am I right?
 
B

Ben Pfaff

I'm wondering of what type a structure is. Of course, it is a
_structure_, but an array isn't an _array_ either.

It isn't? That's news to me.
So of what type is a structure? I'd say a pointer, am I right?

No, a structure is not a pointer nor is it similar to a pointer.
 
M

Minti

damian birchler said:
Hi
I'm wondering of what type a structure is. Of course, it is a
_structure_, but an array isn't an _array_ either. So of what type is
a structure? I'd say a pointer, am I right?

Nopes, there is one simple distinction between a structure and array. Think
about the following


struct Human
{
char *name;
int age;
};


Now look at

Human damian;
Human humans[256];


The *primary*distinction between a structure and an array is that a
structure represents an object/entity as a collection of different
attributes, these attributes may be of different types { above damian has
different attributes name and age }. However in case of an array what you
have is a collection of itmes each having the same type. { humans is an
array, each element of type Human }
 
E

Eric Sosman

damian said:
Hi
I'm wondering of what type a structure is. Of course, it is a
_structure_, but an array isn't an _array_ either. So of what type is
a structure? I'd say a pointer, am I right?

A struct is a struct is a struct. An array is
an array is an array. A rose is a rose is a rose.
None of them is a pointer is a pointer is a pointer.

You seem to be confused on some really fundamental
matter, but I can't tell what it is. In what way do
you think a struct is a pointer, and why do you think
an array is not an array?
 
M

Martin Ambuhl

damian said:
Hi
I'm wondering of what type a structure is. Of course, it is a
_structure_, but an array isn't an _array_ either. So of what type is
a structure? I'd say a pointer, am I right?

An array *is* an array. In particular, it is an array-of-T where T is
the type of a element. What type did you think it to be?

A struct *is* a struct. It isn't something else. Why would you think
otherwise.
 
M

Michael Mair

Hi,

I'm wondering of what type a structure is. Of course, it is a
_structure_, but an array isn't an _array_ either. So of what type is
a structure? I'd say a pointer, am I right?

No.
Perhaps it would help us if you elaborated why you think that an
array is not an array. Otherwise this not so helpful answer certainly
isn't a not so helpful answer.


Guess: You mean an array is not of type "array" but of type "array of
<sometype>".
A structure is exactly of the type you stated it is, that is:

struct {
int x;
char y;
} example;

is of the type "Structure consisting of (in that order) one int,
accessible as x, and one char, accessible as y".

A pointer of type "pointer to <sometype>" contains (if properly
initialized) either NULL or a valid address of an object of type
sometype.

A structure's type is not "pointer".

Note that these explanations are not formally correct; probably
someone else will elaborate or correct what I said.
But I think this helps you more than me posting the respective
parts of the standard:
"6.2.5#20, second item:
A structure type describes a sequentially allocated nonempty set of
member objects (and, in certain circumstances, an incomplete array),
each of which has an optionally specified name and possibly distinct type."
"6.2.7#1
Tw o types have compatible type if their types are the same. Additional
rules for determining whether two types are compatible are described in
6.7.2 for type specifiers, in 6.7.3 for type qualifiers, and in 6.7.5
for declarators.46) Moreover, two structure, union, or enumerated types
declared in separate translation units are compatible if their tags and
members satisfy the following requirements: If one is declared with a
tag, the other shall be declared with the same tag. If both are complete
types, then the following additional requirements apply: there shall be
a one-to-one correspondence between their members such that each pair of
corresponding members are declared with compatible types, and such that
if one member of a corresponding pair is declared with a name, the other
member is declared with the same name. For two structures, corresponding
members shall be declared in the same order. For two structures or
unions, corresponding bit-fields shall have the same widths. For two
enumerations, corresponding members shall have the same values."

Look up the FAQ for pointers, structures and unions as well as types
to help you along:
http://www.eskimo.com/~scs/C-faq/top.html
You can also google for N869, the last C99 draft, which is freely
available. There you can look for struct type and compatibility.


Cheers
Michael
 
?

=?iso-8859-1?q?Nils_O=2E_Sel=E5sdal?=

Hi
I'm wondering of what type a structure is. Of course, it is a
_structure_, but an array isn't an _array_ either. So of what type is
a structure? I'd say a pointer, am I right?
Well, you ,the programmer, define _new_ types with e.g. structures.
 
M

Mike Wahler

damian birchler said:
Hi
I'm wondering of what type a structure is.

It is a 'derived type' (see 9899:1999 6.2.5/20), as well as
an 'aggregate type' (see 9899:1999 6.2.5/21), invented by
the definer of the structure.

struct
{
int a;
};

is a type which has no name.

struct x
{
int a;
};

is a type whose name is 'struct x'
Of course, it is a
_structure_, but an array isn't an _array_ either.

Sure it is. Why would you think otherwise? (an array
is also a 'derived' and 'aggregate' type.)
So of what type is
a structure?

See above.
I'd say a pointer, am I right?

Aboslutely not.

A pointer type is a 'derived type' which describes an object
whose value provides a reference to an entity of the referenced
type (commonly said to represent another object's memory address).

What C book(s) are you reading?

-Mike
 
M

Mike Wahler

Nils O. Selåsdal said:
Well, you ,the programmer, define _new_ types with e.g. structures.

More accurately, these are known as 'derived' types.

-Mike
 
M

Mike Wahler

Mike Wahler said:
A pointer type is a 'derived type' which describes an object
whose value provides a reference to an entity of the referenced
type (commonly said to represent another object's memory address).

For completeness, I must add that a pointer type object can
also represent the predefined value 'NULL', which specifically
indicates 'refers to no object', or 'represents no address'.

-Mike
 
K

Keith Thompson

I'm wondering of what type a structure is. Of course, it is a
_structure_, but an array isn't an _array_ either. So of what type is
a structure? I'd say a pointer, am I right?

As others have said, a structure is a structure, an array is an array,
a pointer is a pointer, and none of these things is either of the
others.

I suspect you've fallen into the trap of believing that an array is
"really" a pointer. It isn't. What causes the confusion is the fact
that an array name, in most contexts, is implicitly converted to a
pointer to its first member. For example:

char message[6] = "hello";
puts(message);

The puts() function expects an argument of type char*, which is
exactly what you're passing to it (because of the implicit conversion)
-- but message is still an array.

This whole thing is further confused by the fact that function
parameter notation makes the following equivalent:

void func(char *s);
void func(char s[]);

But an array is not a pointer; an array name is implicitly converted
to a pointer in most contexts. (The exceptions are when the array
name is the operand of a sizeof or "&" operator; (sizeof message)
gives you the size of the array, not the size of a pointer.)

Read section 6 of the C FAQ, which is available at
<http://www.eskimo.com/~scs/C-faq/top.html>. Then read the whole
thing; you'll be glad you did.
 
M

Malcolm

damian birchler said:
I'm wondering of what type a structure is. Of course, it is a
_structure_, but an array isn't an _array_ either. So of what type is
a structure? I'd say a pointer, am I right?
No. Arrays are passed to subroutines as pointers in C, eg

char name[1024];

/* name converted to a pointer */
strcpy(name, "Fred");

However structures can be passed by value. Eg

#include <stdio.h>

typedef struct
{
int x;
}FOO;

void foo(FOO f);

int main(void)
{
FOO f;
f.x = 42;

printf("f.x %d\n", f.x);
foo(f);
printf(f.x %d\n", f.x);

return 0;


}

void foo(FOO f)
{
f.x = 1;
}

Normally we don't do this, and pass a pointer to a structure, because
structures are often quite large and copying lots of data to the stack
wastes cycles. However then foo must be declared as taking a FOO *.

Internally, a compiler can do as it likes, but it is unlikely to handle
structures as pointers. Probably the structure will be laid out on the stack
as if you had declared the member variables in sequence.
 
D

damian birchler

It's true that I was thinking of a pointer when I said an array wasn't
really an array, but to my self-defence I have to say that I'm not
confused with pointers and arrays ;). What I was asking myself was how
the structure is implemented internally. As far as I know, the ith
member of an array is addressed by adding i multiplied by the size of
the array's elements to the pointer which points to its first element.
Therefore I thought its excately the same with structures. Their
elements are addressed by adding whatever is needed to the pointer
which points to its first element. Of course, because a structure
doesn't consist of equally large members - as it is with arrays, it
matters which element you want to acces. But the idea is the same. Is
this really totally wrong?
 
M

Mike Wahler

damian birchler said:
It's true that I was thinking of a pointer when I said an array wasn't
really an array, but to my self-defence I have to say that I'm not
confused with pointers and arrays ;).

I hope that's true. :)
What I was asking myself was how
the structure is implemented internally.

Not specified by the language (except to make certain restrictions
and allowances). It depends upon the implementation and target
platform.
As far as I know, the ith
member of an array is addressed by adding i multiplied by the size of
the array's elements to the pointer which points to its first element.

Correct. But a struct is not an array.
Therefore I thought its excately the same with structures.

Nope. For one thing, a struct's members are not required to
be the same type or size, those of an array are.
Their
elements are addressed by adding whatever is needed to the pointer
which points to its first element.

Given that such a pointer exists (which is not required for
either a struct or an array), yes. But note that 'whatever is
needed' is not necessarily the sum of the sizes of the members
which might precede it in the struct (see below).
Of course, because a structure
doesn't consist of equally large members - as it is with arrays, it
matters which element you want to acces. But the idea is the same.

The common factor between a struct and an array is that they're
both derived, aggregate types. But that's all.
Is
this really totally wrong?

Conceptually it's pretty close. But there's another issue
you've not mentioned at all (whether oversight or ignorance
I don't know): The members of a struct are not required to
be 'adjacent', that is, an implementation is allowed to (and
quite often does) insert 'padding' bytes between members and/or
after the last member, typically done in the interest of performance
and/or to meet the target platform's memory alignment requirements.
Thisallowance is restricted by one rule: No padding is allowed
before the first member. Thus the address of a struct and that
of its first member are always equal.

The location of any struct member relative to the beginning of a struct
object can be determined by subtracting the struct object's address
from the member's address.

-Mike
 
C

Chris Torek

... I thought its [much] the same with structures. Their
elements are addressed by adding whatever is needed to the pointer
which points to its first element. Of course, because a structure
doesn't consist of equally large members - as it is with arrays, it
matters which element you want to acces. But the idea is the same. Is
this really totally wrong?

It is not *completely* wrong, but it begins with a wrong assumption:
that there is a pointer to the structure in the first place.

Consider the following "struct"s, and an 80x86-CPU implementation:

struct S1 { int s1_i; };
struct S2 { short s2_s1, s2_s2; };

If we write a function that uses two such objects:

void f(void) {
struct S1 a;
struct S2 b;

a.s1_i = 42;
b.s2_s1 = 12;
b.s2_s2 = 0;
... more code that happens not to use b.s2_s2 ...
}

how surprised would you be to find that a compiler put "a" in a
CPU register like %edx? Since "a.s1_i" is a single 32-bit value,
it fits just fine in that register.

Would you be further surprised if the compiler put "b" in another
CPU register? While it contains two "short"s, if b were in, say,
%ecx, the code that uses b.s2_s1 could use the %cx "register half"
on the CPU to access the desired sub-half. (It is important that
this code not use b.s2_s2 because that would, on this compiler,
reside in the upper half of %ecx, where it is difficult to extract
or insert without disturbing the %cx half.)

More generally, structure members must be "remembered" in a C
compiler (at compile-time) as a pair of values: an offset, and a
type. The type is the same as that used for any ordinary variable
-- e.g., if the compiler happens to use numbers internally, and
uses "7" for "int", the member s1_i in "struct S1" might be
represented as the pair <0,7>. If "short" is type-code 5, the two
members in struct S2 might be <0,5> and <2,5> respectively.

Before the kind of optimization that might put struct values into
CPU registers, then, the compiler does indeed use the kind of
address-offsetting you are considering. If one has a structure
object in memory, one need only use the offset:

mov.l #42,mem_for_a+0 // a.s1_i = 42
mov.w #12,mem_for_b+0 // b.s1_s1 = 12
mov.w #0,mem_for_b+2 // b.s1_s2 = 0

while if one has a pointer, one must follow the pointer and add
the offset:

mov.l #42,0(a_ptr) // a->s1_i = 42
mov.w #12,0(b_ptr) // b->s1_s1 = 12
mov.w #0,2(b_ptr) // b->s1_s2 = 0

(all in some hypothetical assembly language).

The C standard requires that structure member offsets be allocated
in ascending order, and that the first one be zero; but between
any two structure members, there may be an arbitrary amount of
padding. Typically, C compilers use this "padding license" to make
sure that structure members are aligned on "natural" boundaries
for the underlying machine -- e.g., a struct containing a char
followed by an int may have (sizeof(int)-1) bytes of padding between
them. Padding may also be added at the end of a structure, so that
arrays of structures are similarly aligned. (Bitfields are a
special case that is somewhat difficult to describe, and two
compilers for the same machine may well use different bitfield
allocation orders. C compilers targeting the Motorola 680x0 CPUs
tended to do this for reasons that are more obvious if you were
writing 68010 assembly code when the 68020 first came out.)

Very early C compilers actually permitted almost any lvalue on the
left of a "." operator. I once rewrote a program that contained
code like this:

struct { char lo, hi; };
short w;

w = somefunc();
printf("the bytes in octal are: %o, %o\n", w.lo, w.hi); /* GAK */

Even in the late 1980s, this code still compiled (with very loud
warnings) on the VAX "portable C compiler" (PCC). This was already
dodgy, and was not going to be part of ANSI C (this was part of the
reason to rewrite the program) -- but it shows how the concept
evolved, at least.
 
K

Keith Thompson

It's true that I was thinking of a pointer when I said an array wasn't
really an array, but to my self-defence I have to say that I'm not
confused with pointers and arrays ;). What I was asking myself was how
the structure is implemented internally. As far as I know, the ith
member of an array is addressed by adding i multiplied by the size of
the array's elements to the pointer which points to its first element.
Therefore I thought its excately the same with structures. Their
elements are addressed by adding whatever is needed to the pointer
which points to its first element. Of course, because a structure
doesn't consist of equally large members - as it is with arrays, it
matters which element you want to acces. But the idea is the same. Is
this really totally wrong?

Array indexing is defined in terms of pointer arithmetic. a is by
definition equivalent to *(a+i). One consequence of this is that you
can't legally index an array object declared with the "register"
keyword (not that there's any good reason to do so).

Access to structure members is not defined that way; it just needs to
work. For example, bit fields don't have addresses, but you can still
access their values. (The generated code is likely to do some kind of
address computation, but the details aren't specified by the standard
the way they are for array indexing.)

One could argue that array semantics are over-specified in C (in some
other languages, indexing "just works" without explicitly depending on
address arithmetic). On the other hand, there are advantages to being
able to step through an array by advancing a pointer rather than an
index.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,148
Messages
2,570,834
Members
47,380
Latest member
AlinaBlevi

Latest Threads

Top