Struct (C programming language)
Encyclopedia
A struct in C programming language is a structured (record
Record (computer science)
In computer science, a record is an instance of a product of primitive data types called a tuple. In C it is the compound data in a struct. Records are among the simplest data structures. A record is a value that contains other values, typically in fixed number and sequence and typically indexed...

) type that aggregates a fixed set of labelled objects, possibly of different types, into a single object.

A struct declaration consists of a list of fields, each of which can have any type. The total storage required for a struct object is the sum of the storage requirements of all the fields, plus any internal padding.

For example:

struct account {
int account_number;
char *first_name;
char *last_name;
float balance;
};


defines a type, referred to as struct account. To create a new variable of this type, we can write

struct account s;

which has an integer component, accessed by s.account_number, and a floating-point component, accessed by s.balance, as well as the first_name and last_name components. The structure s contains all four values, and all four fields may be changed independently.

The primary use of a struct is for the construction of complex
datatypes, but in practice they are sometimes used to circumvent standard C conventions to create a kind of primitive subtyping
Subtype
In programming language theory, subtyping or subtype polymorphism is a form of type polymorphism in which a subtype is a datatype that is related to another datatype by some notion of substitutability, meaning that program constructs, typically subroutines or functions, written to operate on...

. For example, common Internet protocols rely on the fact that C compilers insert padding between struct fields in predictable ways; thus the code

struct ifoo_version_42 {
long x, y, z;
char *name;
long a, b, c;
};
struct ifoo_old_stub {
long x, y;
};
void operate_on_ifoo(struct ifoo_version_42 *);
struct ifoo_old_stub s;
. . .
operate_on_ifoo(&s);


is often assumed to work as expected, if the operate_on_ifoo function only accesses fields x and y of its argument.

Struct initialization

There are two ways to initialize a structure. The C89-style initializers are used when contiguous members may be given.


/* Define a type point to be a struct with integer members x, y */
typedef struct {
int x;
int y;
} point;

/* Define a variable p of type point, and initialize all its members inline! */
point p = {1,2};


For non contiguous or out of order members list designated initializer style may be used



/* Define a variable p of type point, and set members using designated initializers*/
point p = {.y = 2, .x = 1};


Omitted elements are initialised to 0. The disadvantage of designated initializer style is that this feature is not defined for C++ programming language, according to C++11 standard

Assignment

The following assignment of a struct to another struct does what one might expect. It is not necessary to use memcpy to make a duplicate of a struct type. The memory is already given and zeroed by just declaring a variable of that type regardless of member initialization. This should not be confused with the requirement of memory management when dealing with a pointer to a struct.

  1. include


/* Define a type point to be a struct with integer members x, y */
typedef struct {
int x;
int y;
} point;

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

/* Define a variable p of type point, and initialize all its members inline! */
point p = {1,2};

/* Define a variable q of type point. Members are initialized with the defaults for their derivative types such as 0. */
point q;

/* Assign the value of p to q, copies the member values from p into q. */
q = p;

/* Change the member x of q to have the value of 2 */
q.x = 2;

/* Demonstrate we have a copy and that they are now different. */
if (p.x != q.x) printf("The members are not equal! %d != %d", p.x, q.x);
}

Pointers to struct

Pointers can be used to refer to a struct by its address. This is particularly useful for passing structs to a function by reference. The pointer can be dereferenced just like any other pointer in C — using the * operator. There is also a -> operator in C which dereferences the pointer to struct (left operand) and then accesses the value of a member of the struct (right operand).


struct point {
int x;
int y;
} my_point;

struct point *p = &my_point; /* To declare p as a pointer of type struct point */

(*p).x = 8; /* To access the first member of the struct */
p->x = 8; /* Another way to access the first member of the struct */


typedef

Typedef
Typedef
typedef is a keyword in the C and C++ programming languages. The purpose of typedef is to assign alternative names to existing types, most often those whose standard declaration is cumbersome, potentially confusing, or likely to vary from one implementation to another.Under C convention , types...

s can be used as shortcuts, for example:


typedef struct account {
int account_number;
char *first_name;
char *last_name;
float balance;
} account;


Different users have differing preferences; proponents usually claim:
  • shorter to write
  • can simplify more complex type definitions, such as a type that defines a pointer to a function that accepts pointers to struct types and returns a pointer to struct:


Without typedef:

struct point {
int x;
int y;
};
typedef struct point *(*point_compare_t) (struct point *a, struct point *b);

With typedef:


struct point {
int x;
int y;
};
typedef struct point point_t;
typedef point_t *(*point_compare_t) (point_t *a, point_t *b);


If neither typedef were used in defining a function that takes a pointer to a type of the above function pointer, the following code would have to be used. Although valid, it becomes increasingly hard to read quickly.


/* Define our struct point type */
struct point {
int x;
int y;
};

/* Define a function that returns a pointer to the biggest point, using a function to do the comparison. */
struct point *biggest_point (size_t size, struct point *points, struct point *(*point_compare) (struct point *a, struct point *b))
{
int i;
struct point *biggest = NULL;

for (i=0; i < size; i++) {
biggest = point_compare(biggest, points + i);
}
return biggest;
}


However, there are a handful of disadvantages in using them:
  • they pollute the main namespace (see below), however this is easily overcome with prefixing a library name to the type name.
  • harder to figure out the aliased type (having to scan/grep through code)
  • typedefs do not really "hide" anything in a struct or union — members are still accessible (account.balance)
    (To really hide struct members, one needs to use 'incompletely-declared' structs.)



/* Example for namespace clash */

typedef struct account { float balance; } account;
struct account account; /* possible */
account account; /* error */

See also

  • C language union
  • Composite data type
The source of this article is wikipedia, the free encyclopedia.  The text of this article is licensed under the GFDL.
 
x
OK