Pointeurs

Résolu/Fermé
JeVeuxJusteEtreIngenieure - Modifié le 24 janv. 2023 à 17:00
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 - 23 janv. 2023 à 17:23

Bonjour,

Je ne comprends pas la résolution d'un énoncé d'un exercice d'informatique, pouvez-vous m'aider svp.

L'énoncé :Écrire en C une fonction prenant en arguments quatre réels x, y, z et r, et retournant un pointeur vers une représentation de la sphère correspondante, nouvellement allouée. Si la valeur fournie pour le rayon r est négative ou nulle, alors la fonction doit retourner un code d’erreur, sous la forme d’un pointeur nul.

La résolution proposée par le prof :

#include <stdlib.h>

struct sphere *nouvelle_sphere(double x, double y, double z, double r)
{
  struct sphere *s;
 
  if (r < 0.0)
    return NULL;
 
  s = malloc(sizeof(struct sphere));

  if (!s)
    return NULL;

  s -> x = x;
  s -> y = y;
  s -> z = z;
  s -> r = r;
  return s;
}

Je comprends le début mais pas les dernières lignes avec "s -> x =x;" 

Merci pour votre réponse !!!

3 réponses

[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
23 janv. 2023 à 10:42

Salut JeVeuxJusteEtreIngenieure, 

La notation -> sert à déréférencer un pointeur sur struct pour accéder aux membres de la struct pointée.

Donc, si sphere est de type pointeur sur struct et contient l'adresse mémoire valide vers un espace mémoire alloué, pour accéder aux membres, il faut bien faire :

struct sphere *s;
s = malloc(sizeof(sphere));
if (s == NULL) {
    // traiter l'erreur
}
s->x = 12;

Comme il est très fréquent en C, d'utiliser des pointeurs sur struct pour accéder indirectement aux données stockées, le C propose l'opérateur -> qui est un opérateur pratique, évitant d'avoir à écrire (*s).x.

Les parenthèses seraient, en effet, nécessaires pour déréférencer le pointeur, car en C l'opérateur . d'accès aux membres d'une struct a priorité sur l'opérateur * d'indirection.

https://en.cppreference.com/w/c/language/operator_precedence

Si en revanche sphere est de type struct, il faut naturellement accéder aux membres avec l'opérateur . d'accès aux membres.

struct sphere s;
s.x = 12;

2
Utilisateur anonyme
23 janv. 2023 à 10:47

Salut, en voyant ta réponse je me suis rendu compte d'une erreur dans ma redaction, j'ai écrit que s est de type sphere, or, comme tu le soulignes s est de type point sur sphere.

Ton explication plus complète, rétablit au passage ma coquille.

Bonne journée 

0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092 > Utilisateur anonyme
Modifié le 23 janv. 2023 à 17:30

Pas de soucis et merci pour ton commentaire :-)

Voilà d'autres infos utiles à la compréhension globale des struct.

En C, les pointeurs sur struct sont fréquemment utilisés en paramètres des fonctions, que l'on ait besoin de modifier le contenu de la struct ou pas, car ils sont plus économes en mémoire et ressources que de passer des struct en paramètres. En effet, par défaut, si on passe une struct (et non un pointeur sur struct), les struct sont alors copiées dans leur intégralité lors du passage de paramètres dans une copie de la struct locale à la fonction. C'est particulièrement utile de passer des pointeurs sur struct lorsque les struct agrègent de nombreuses données.

Par exemple, une struct qui contiendrait un tableau pouvant accueillir tous les objets d'une scène 3D et regroupant toutes les autres informations nécessaires à la description de la scène, avec les données relatives à la caméra 3D, etc. Si on veut signifier dans le prototype que le contenu pointé n'est pas censé être modifié par la fonction, on peut déclarer le prototype comme étant const struct scene *.

#define MAX_NB_OBJECTS 200

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

struct camera {
    struct point location;
    struct point look_at;
};

enum object_types { SPHERE, CUBE, CONE };

struct sphere {
    struct point centre;
    int radius;
};

struct cube {
    /* TODO */
};

struct cone {
    /* TODO */
};

struct scene {
    char scene_name[255];
    struct camera camera;
    int nb_objects;
    union {
         enum object_types type;
         struct sphere sphere;
         struct cube cube;
         struct cone cone;
    } objets[MAX_NB_OBJECTS]; 
};

void draw_scene(const struct scene * scene) {
    /* TODO */
}

En passant un pointeur sur struct, seule l'adresse contenue dans la variable pointeur est copiée lors du passage de paramètres, et pas toutes les données contenues dans la struct. L'appel à la fonction est extrêmement rapide et ne consomme presque rien de plus en termes de mémoire (juste de quoi stocker l'adresse mémoire de la struct). Comme c'est un prototype void draw_scene(const struct scene * scene); on sait que cette fonction n'est pas sensée modifier le contenu de la struct quand bien même un pointeur est passé en raison de l'usage du qualificateur de type const.

Evidemment, si le contenu de la struct doit être modifié par la fonction à laquelle on passe la struct en paramètre, il est indispensable de lui passer un pointeur sur struct (non const).

Par exemple :

void sphere_modify_radius(struct sphere * s, double r) {
    s->r = r;
}
0
Utilisateur anonyme
22 janv. 2023 à 08:51

Bonjour

tout d'abord, pour poster ton code, il faut faire comme décrit là, https://codes-sources.commentcamarche.net/faq/11288-poster-un-extrait-de-code et surtout préciser que le langage que tu utilises.

mais pas les dernières lignes avec "s -> x =x;" 

Voir mes commentaires dans le code,

#include <stdlib.h>

struct sphere *nouvelle_sphere(double x, double y, double z, double r)

{
  struct sphere *s;

  if (r < 0.0)
    return NULL;

  s = malloc(sizeof(struct sphere)); //ici, on alloue un espace mémoire suffisant pour y stocker les données d'une structure "sphere"
  
  if (!s)
    return NULL;

  //mais pour l'instant, cette sphere est vide de données.
  //A priori, dans la structure, il y a au moins 4 attributs
      //un qui s'appelle x
      //un qui s'appelle y
      //un qui s'appelle z
      //un qui s'appelle r
  //il faut donc remplir ces attributs

  s -> x = x;//s -> x veut dire l'attribut x de la variable s de type sphere. Cette ligne veut donc dire que l'on affecte la valeur de la variable x passée en paramètre à l'attribut x de s
  s -> y = y;
  s -> z = z;
  s -> r = r;
return s;

}

Au passage, tu vois les intérêts d'utiliser correctement la coloration syntaxique


0
JeVeuxJusteEtreIngenieure
22 janv. 2023 à 09:40

Un grand merci pour votre réponse et pour les conseils !!

Bonne journée

0
Utilisateur anonyme
22 janv. 2023 à 10:27

de rien.

Pense à marquer le sujet résolu


0