Loading lang_c_07_struct...
struct MyStruct // définition de la structure nommée MyStruct { int i, j; // une instance de la structure MyStruct est constituée de deux entiers double d; // et d'un réel };
... { struct MyStruct v1, v2; // les variables v1 et v2 sont des instances de la structure MyStruct ... }
struct MyStruct // définition du type struct MyStruct { int i, j; double d; };
typedef struct MyStruct MyType; // le type nommé MyType équivaut à struct MyStruct
... { MyType v1, v2; // deux instances de struct MyStruct ... }
typedef struct // une structure simple { int i, j; double d; } MyType;
typedef struct Node // une structure auto-référencée { int value; struct Node *next; } Node;
typedef struct { double x, y, z; } Vec3D;
typedef struct { double radius, mass; Vec3D pos, vel; } Particle;
... { Particle p1, p2; ... }
... { Particle p; // type Particle de l'exemple précédent p.radius=0.5; // modification d'un membre p.vel.z=-0.8; // modification d'un sous-membre printf("radius=%g vel_z=%g\n", p.radius, p.vel.z); // radius=0.5 vel_z=-0.8 ... }
->(flèche) permet toutefois de simplifier l'écriture.
typedef struct { int i, j; double d; } MyType;
... { MyType v1, *v2=&v1, v3[4]; v2->i=1; // équivaut à (*v2).i=1; v2->j=10; // équivaut à (*v2).j=10; v2->d=1.1; // équivaut à (*v2).d=1.1; for(int i=0; i<4; ++i) { v3[i].i=1+v2->i; v3[i].j=10+v2->j; v3[i].d=1.1+v2->d; v2=v3+i; } printf("last: i=%d j=%d d=%g\n", // last: i=5 j=50 d=5.5 v2->i, v2->j, v2->d); ... }
->(flèche).
// ... types MyType et Particle des exemples précédents ...
... { MyType v1; // les membres ont des valeurs indéterminées MyType v2={1, 10, 1.1}; // les trois membres explicitement initialisés MyType v3={1, 10}; // les deux premiers membres spécifiés, le dernier à zéro MyType v4[]={{2, 20, 2.2 }, // initialisation des trois structures d'un tableau {3}, {4, 40}}; Particle v5={0.1, 4.5, // membres radius et mass {0.0, 0.0, 5.0}, // membre pos {1.0, 0.0, 1.0}}; // membre vel ... }
// ... type MyType des exemples précédents ...
MyType doSomething(MyType v) // passage par valeur, recopie du paramètre effectif { v.i*=2; // modification du paramètre formel v.j*=3, v.d*=4.0; return v; // renvoi d'une copie }
... dans une autre fonction ... { MyType v1={1,10, 1.1}, v2; v2=doSomething(v1); // passage par valeur, renvoi puis affectation printf("v1: i=%d j=%d d=%g\n", v1.i, v1.j, v1.d); // v1: i=1 j=10 d=1.1 printf("v2: i=%d j=%d d=%g\n", v2.i, v2.j, v2.d); // v2: i=2 j=30 d=4.4 ... }
typedef struct { double xyz[3]; } XYZ;
XYZ doSomething(XYZ v) { v.xyz[0]*=2.0; v.xyz[1]*=3.0; v.xyz[2]*=4.0; return v; }
... dans une autre fonction ... { XYZ v1={{ 1.1, 2.2, 3.3}}, v2; v2=doSomething(v1); // passage par valeur, renvoi puis affectation printf("v1: %g %g %g\n", v1.xyz[0], v1.xyz[1], v2.xyz[2]); // v1: 1.1 2.2 3.3 printf("v2: %g %g %g\n", v2.xyz[0], v2.xyz[1], v2.xyz[2]); // v2: 2.2 6.6 13.2 ... }
typedef struct { char a; char b; char c; char d; int e; int f; int g; int h; } S1;
typedef struct { char a; int e; int f; int g; int h; } S2;
typedef struct { int e; char a; int f; char b; int g; char c; int h; char d; } S3;
... { printf("sizeof: char=%d\tint=%d\n", // sizeof: char=1 int=4 (int)sizeof(char), (int)sizeof(int)); printf("sizeof: S1=%d\tS2=%d\tS3=%d\n", // sizeof: S1=20 S2=20 S3=32 (int)sizeof(S1), (int)sizeof(S2), (int)sizeof(S3)); ... }
int // l'écart en octets entre deux adresses byteOffset(const void *addr1, const void *addr2) { const char *p1=(const char *)addr1; const char *p2=(const char *)addr2; return (int)(p2-p1); }
... dans une autre fonction ... { S1 v1; // les même structures S1, S2 et S3 que dans l'exemple précédent S2 v2; S3 v3; printf("S1: a_to_b=%d a_to_e=%d e_to_f=%d\n", // S1: a_to_b=1 a_to_e=4 e_to_f=4 byteOffset(&v1.a,&v1.b), byteOffset(&v1.a,&v1.e), byteOffset(&v1.e,&v1.f)); printf("S2: a_to_e=%d e_to_f=%d\n", // S2: a_to_e=4 e_to_f=4 byteOffset(&v2.a,&v2.e), byteOffset(&v2.e,&v2.f)); printf("S3: e_to_a=%d a_to_f=%d f_to_b=%d\n", // S3: e_to_a=4 a_to_f=4 f_to_b=4 byteOffset(&v3.e,&v3.a), byteOffset(&v3.a,&v3.f), byteOffset(&v3.f,&v3.b)); ... } /* S1: |a|b|c|d|e . . .|f . . .|g . . .|h . . .| S2: |a|? ? ?|e . . .|f . . .|g . . .|h . . .| S3: |e . . .|a|? ? ?|f . . .|b|? ? ?|g . . .|c|? ? ?|h . . .|d|? ? ?| */
#ifndef VEC3D_H #define VEC3D_H
typedef struct { double x, y, z; } Vec3D;
Vec3D // (x, y, z) vector Vec3D_set(double x, double y, double z);
Vec3D // (0.0, 0.0, 0.0) vector Vec3D_zero(void);
Vec3D // vector addition: v+w vector Vec3D_plus(Vec3D v, Vec3D w);
Vec3D // vector scaling: v*d vector Vec3D_times(Vec3D v, double d);
double // dot product: v*w scalar Vec3D_dot(Vec3D v, Vec3D w);
double // vector magnitude: scalar Vec3D_mag(Vec3D v);
Vec3D // unit length vector Vec3D_unit(Vec3D v);
#endif // VEC3D_H
#include "vec3D.h" #include <math.h> // adjust linker settings in GNUmakefile: LDFLAGS+=-lm
Vec3D // (x, y, z) vector Vec3D_set(double x, double y, double z) { Vec3D v={x, y, z}; return v; }
Vec3D // (0.0, 0.0, 0.0) vector Vec3D_zero(void) { return Vec3D_set(0.0, 0.0, 0.0); }
Vec3D // vector addition: v+w vector Vec3D_plus(Vec3D v, Vec3D w) { return Vec3D_set(v.x+w.x, v.y+w.y, v.z+w.z); }
Vec3D // vector scaling: v*d vector Vec3D_times(Vec3D v, double d) { return Vec3D_set(v.x*d, v.y*d, v.z*d); }
double // dot product: v*w scalar Vec3D_dot(Vec3D v, Vec3D w) { return v.x*w.x+v.y*w.y+v.z*w.z; }
double // vector magnitude: scalar Vec3D_mag(Vec3D v) { return sqrt(Vec3D_dot(v, v)); }
Vec3D // unit length vector Vec3D_unit(Vec3D v) { return Vec3D_times(v, 1.0/Vec3D_mag(v)); }
#include <stdio.h> #include "vec3D.h"
int main(void) { Vec3D v[5]={Vec3D_zero()}; for(int i=1; i<5; ++i) { v[i]=Vec3D_plus(v[i-1], Vec3D_times(Vec3D_set(i, i+1, i+2), 0.2)); } Vec3D dir=Vec3D_unit(v[4]); printf("%g %g %g\n", dir.x, dir.y, dir.z); // 0.40161 0.562254 0.722897 return 0; }
<math.h>et la modification du fichier GNUmakefile sont nécessaires dans cet exemple car nous utilisons la fonction mathématique standard sqrt() qui calcule la racine carrée d'un réel (ceci sera étudié dans cette section).
#ifndef MEM_H #define MEM_H
typedef struct { int c; int *d; } Mem;
// determine initial state Mem Mem_create(void);
// free resources void Mem_destroy(Mem *m);
// number of values int Mem_count(const Mem *m);
// get value at index int Mem_get(const Mem *m, int index);
// set value at index void Mem_set(Mem *m, int index, int value);
// memorise a new value void Mem_append(Mem *m, int value);
// display values void Mem_show(const Mem *m);
#endif // MEM_H
#include "mem.h" #include <stdlib.h> #include <stdio.h>
// determine initial state Mem Mem_create(void) { Mem m={0, NULL}; return m; }
// free resources void Mem_destroy(Mem *m) { free(m->d); m->c=0; m->d=NULL; }
// number of values int Mem_count(const Mem *m) { return m->c; }
// get value at index int Mem_get(const Mem *m, int index) { return m->d[index]; }
// set value at index void Mem_set(Mem *m, int index, int value) { m->d[index]=value; }
// memorise a new value void Mem_append(Mem *m, int value) { m->d=(int *)realloc(m->d, (1+m->c)*sizeof(int)); m->d[m->c++]=value; }
// display values void Mem_show(const Mem *m) { for(int i=0; i<m->c; ++i) { printf("%d ", m->d[i]); } printf("\n"); }
#include "mem.h"
int main(void) { Mem m=Mem_create(); // initialisation Mem_append(&m, 1); // mémorisation Mem_append(&m, 2); Mem_append(&m, 3); for(int i=0, count=Mem_count(&m); i<count; ++i) { Mem_set(&m, i, Mem_get(&m,i)*10); // modification } Mem_show(&m); // 10 20 30 Mem_destroy(&m); // libération des ressources return 0; }
#include <stdio.h> #include "mem.h"
int main(void) { Mem m1=Mem_create(); // initialisation de m1 Mem_append(&m1, 1); // mémorisation dans m1 Mem_append(&m1, 2); Mem_append(&m1, 3); Mem m2=m1; // copie incorrecte de m1 vers m2 !!! for(int i=0, count=Mem_count(&m2); i<count; ++i) { Mem_set(&m2, i, Mem_get(&m2, i)*100); // modification de m2 (et donc de m1 !!!) } printf("m1: "); Mem_show(&m1); // m1: 100 200 300 Mem_destroy(&m1); // libération de m1.d (et de m2.d !!!) Mem_append(&m2,400); // la suite travaille sur Mem_append(&m2,500); // une zone mémoire libérée, printf("m2: "); // le comportement est Mem_show(&m2); // alors indéfini Mem_destroy(&m2); // (plantage probable) return 0 ; }
#ifndef VEC3D_H #define VEC3D_H
#include <math.h> // adjust linker settings in GNUmakefile: LDFLAGS+=-lm
typedef struct { double x, y, z; } Vec3D;
inline static Vec3D // (x, y, z) vector Vec3D_set(double x, double y, double z) { Vec3D v={x, y, z}; return v; }
inline static Vec3D // (0.0, 0.0, 0.0) vector Vec3D_zero(void) { return Vec3D_set(0.0, 0.0, 0.0); }
inline static Vec3D // vector addition: v+w vector Vec3D_plus(Vec3D v, Vec3D w) { return Vec3D_set(v.x+w.x, v.y+w.y, v.z+w.z); }
inline static Vec3D // vector scaling: v*d vector Vec3D_times(Vec3D v, double d) { return Vec3D_set(v.x*d, v.y*d, v.z*d); }
inline static double // dot product: v*w scalar Vec3D_dot(Vec3D v, Vec3D w) { return v.x*w.x+v.y*w.y+v.z*w.z; }
inline static double // vector magnitude: scalar Vec3D_mag(Vec3D v) { return sqrt(Vec3D_dot(v, v)); }
inline static Vec3D // unit length vector Vec3D_unit(Vec3D v) { return Vec3D_times(v, 1.0/Vec3D_mag(v)); }
#endif // VEC3D_H
#ifndef MEM_H #define MEM_H
#include <stdlib.h>
typedef struct { int c; int *d; } Mem;
// determine initial state inline static Mem Mem_create(void) { Mem m={0, NULL}; return m; }
// free resources void Mem_destroy(Mem *m);
// number of values inline static int Mem_count(const Mem *m) { return m->c; }
// get value at index inline static int Mem_get(const Mem *m, int index) { return m->d[index]; }
// set value at index inline static void Mem_set(Mem *m, int index, int value) { m->d[index]=value; }
// memorise a new value void Mem_append(Mem *m, int value);
// display values void Mem_show(const Mem *m);
#endif // MEM_H
<stdlib.h>(nous le ferons dans les autres fonctions), nous l'incluons pour rendre la macro NULL accessible.
#include "mem.h" #include <stdio.h>
// free resources void Mem_destroy(Mem *m) { free(m->d); m->c=0; m->d=NULL; }
// memorise a new value void Mem_append(Mem *m, int value) { m->d=(int *)realloc(m->d, (1+m->c)*sizeof(int)); m->d[m->c++]=value; }
// display values void Mem_show(const Mem *m) { for(int i=0; i<m->c; ++i) { printf("%d ", m->d[i]); } printf("\n"); }