0
votes

Alloué de mémoire pour une structure dans une fonction qui renvoie le pointeur à la structure

J'essaie de créer une structure qui représente une matrice mathématique bidimensionnelle.

La fonction 'initmatrix' est destinée à initialiser une matrice de n lignes N par n colonnes, avec les éléments stockés dans une matrice allouée de manière dynamique de Double et réglé à zéro. P>

Cependant, lorsque j'essaie d'attribuer zéro à la matrice par le pointeur "Données" dans la structure (selon cette question) , cela provoque l'échec du programme. P>

#include <stdio.h>
#include <stdlib.h>

typedef struct
{
  int rows;
  int cols;
  double *data;
} Matrix;

Matrix *initMatrix(int rows, int cols)
{
  Matrix *ptr;
  ptr = (Matrix *)malloc(sizeof(int) * 2 + sizeof(double) * rows * cols);
  if(ptr == NULL) printf("Couldn't allocate memory");
  for(int i = 0; i < rows; i++) {
    for(int j = 0; j < cols; j++) {
      *(ptr->data) = 0; //error originating here
      ptr->data++;
    }
  }
  return ptr;
}

int main(void) 
{
  Matrix *mptr = initMatrix(2, 2);

  return 0;
}

c

0 commentaires

4 Réponses :


2
votes
ptr = malloc(sizeof(Matrix));
ptr -> data = malloc(sizeof(int) * 2 + sizeof(double) * rows * cols);

0 commentaires

6
votes

comme data ​​code> est un pointeur sur une région de mémoire, vous devrez maîtriser cette région séparément, c'est-à-dire

Matrix initMatrix(int rows, int cols)
{
  Matrix result;
  result.data = (double *)malloc(sizeof(double) * rows * cols);

  if(result.data == NULL) printf("Couldn't allocate memory");

  result.rows = rows;
  result.cols = cols;

  // initialization of result.data here, consider using memset() ...
  return result;
}


3 commentaires

Vous devez toujours zéro la matrice (utilisez calloc ) et initialiser les autres membres, mais OP n'a pas fait cette dernière pièce (oubliée) non plus.


BTW si (résultat.data == null) printf ("Impossible d'attribuer la mémoire"); est plutôt inutile, il affichera le message si malloc échoue mais ce qui se passe ensuite?


@Paulogilvie: a ajouté l'initialisation du membre



2
votes

Vous devez attribuer la mémoire pour les données séparément et pour la matrice séparément. Vous devez également libérer la mémoire allouée à l'intérieur de la fonction initmatrix dans votre principal () .

En plus de ce que toutes les autres très bonnes réponses ont mentionné à propos de l'utilisation de Memset () ou calloc () au lieu de le faire vous-même dans 2 pour boucles, etc., je veux mentionner quelques choses que le D'autres affiches n'ont pas répondu, et aussi à capturer l'essentiel ce que je sens que l'OP demandait:

  1. Vous confondez une matrice qui nécessite un double ** Data avec un vecteur 1-D contenant le même nombre d'éléments et peut être stocké dans double * Données < / code>.

    C'est pourquoi vous utilisez les deux pour boucles, je suppose. Vous ne voulez pas 4 éléments dans une ligne 1. Vous voulez 2 lignes et 2 cols! Vous pouvez regarder le code ci-dessous pour voir comment cela peut être atteint.

  2. N'oubliez pas de libérer à la fois le MPTR et les données .

  3. En plus de votre code, vous n'initialisez pas ptr-> cols et ptr-> lignes . .

    code: xxx

    qui produit la sortie:

    lignes: 2, cols: 2
    Element [0] [0]: 0.000000
    Element [0] [1]: 1.000000
    Element [1] [0]: 10.000000
    Element [1] [1]: 11.000000

    que je viens d'afficher pour déboguer. Vous pouvez modifier la ligne ptr-> data [i] [j] = i * 10 + j; et obtenir la sortie que vous souhaitez, y compris tous les zéros.


1 commentaires

@Jabberwocky, j'ai édité ma réponse et le code. J'avais trouvé d'autres faussades dedans que j'ai corrigé. De plus, concernant MALLOC () échec, si MALLOC () échoue, puis au meilleur de mes connaissances et de mes connaissances, il est temps d'emballer et de rentrer chez vous :) . Mis à part, cela dépend de l'emplacement de ce bit de code. S'il s'agit d'un dispositif intégré, nous avons de graves problèmes à résoudre. Oui printf serait inutile dans ce cas (sauf peut-être pour vous connecter, car le message d'erreur sur l'échec MALLOC n'entrera pas dans le journal lui-même).



1
votes

Si vous souhaitez attribuer toute la structure avec un MALLOC , vous pouvez utiliser xxx

contrairement aux autres réponses qui permet d'utiliser un seul GRATUIT .

Si votre compilateur prend en charge des tableaux de taille 0, vous pouvez également utiliser double données [0]; .

à partir de C99 Peut utiliser un tableau sans dimension dans la structure: Double données []; , voir https: // Stackoverflow. com / a / 2061038/10622916

au lieu de calculer la taille de MALLOC en ajoutant la taille des types de champs de structure "Vous devez mieux utiliser Taillef ou offsetof avec le type de structure matrice car il peut y avoir un peu de remplissage. (Probablement pas dans votre cas, mais cela dépend de la mise en œuvre du compilateur et de vos champs de structure.) xxx

au lieu d'incrémenter le pointeur DATA Vous pouvez calculer le index de tableau xxx

ou pour l'initialisation 0, vous pouvez utiliser Memset xxx

ou utiliser calloc (1 , offsetof (matrice, données) + tailleof (double) * lignes * cols); au lieu de malloc pour obtenir zéro mémoire initialisée.


1 commentaires

Pour l'initialisation zéro, utilisez calloc () au lieu de malloc .