0
votes

est-ce la bonne façon d'initialiser un pointeur vers struct? Je vous remercie

comment créer un pointeur pour structurer correctement?

typedef struct account{

char name[80];

int acct_year;

}account;

int main
{
account *accountant;// is this the proper way?
}


2 commentaires

Cela crée une variable du type approprié, mais cela ne crée pas d'instance de la structure, ni n'initialise la valeur du pointeur.


Mais vraiment, pour ce genre de question, il vaut mieux suivre un tutoriel que d'essayer de poser des questions sur chaque détail qui apparaît sur Stack Overflow.


3 Réponses :


-1
votes

La manière habituelle est d'utiliser l'appel système malloc () pour allouer un bloc de mémoire gros pour votre type de structure sur le tas système. Vous voudrez vérifier que cela s'est réellement passé au cas où vous n'auriez plus de mémoire.

free (accountant);

Lorsque vous avez terminé ASSUREZ-VOUS de libérer le bloc dans le système avec

    account * accountant;
    
    if ((accountant = malloc ( sizeof(struct account))) == NULL)
    {
              errno = ENOMEM;
              return some error token.
    }

...continue knowing the pointer has been initialised.


0 commentaires

0
votes

J'ai écrit des commentaires dans le code pour expliquer les choses. Faites-moi savoir si toujours déroutant.

#include <stdio.h>

// This is needed for strncpy
#include <string.h>

// This is needed for malloc
#include <stdlib.h>

struct Account {
    char name[80];
    int acct_year;
};

int main()
{
    // Normal declaration of a variable of type Account
    struct Account userAccount;


    // Using strncpy is safer than using strcpy. Read about overflow buffer attack.
    char* userName = "Alex";
    strncpy(userAccount.name, userName, sizeof(userName));
    
    userAccount.acct_year = 4;
    printf("User Account: %s %d\n", userAccount.name, userAccount.acct_year);
    
    // Creating a pointer to access the struct we declare and initiate above;
    struct Account *pUserAccount;
    
    // Pass the address of the variable above inside the pointer
    pUserAccount = &userAccount; 
    
    // We can replace the value in userAccount from the pointer
    pUserAccount->acct_year = 5; 
    
    // Compare to see that we changed the value in userAccount using the pointer
    printf("Pointer User Account: %s %d\n", pUserAccount->name, pUserAccount->acct_year);
    printf("User Account: %s %d\n", userAccount.name, userAccount.acct_year);
    
    
    // Let's create a pointer and give it some space from the Heap memory
    struct Account *pAdminAccount;
    pAdminAccount = malloc(sizeof (struct Account));
    
    // We always check because we could have run out of memory or something failed
    if (pAdminAccount != NULL) {
        // Due my lazyness, I am copying the name from userAccount inside pAdminAccount
        strncpy(pAdminAccount->name, userAccount.name, sizeof(userAccount.name));
        pAdminAccount->acct_year = 6;
        printf("Pointer Heap Adminr Account: %s %d\n", pAdminAccount->name, pAdminAccount->acct_year);
    
        // Always free the memory when you are not using it.    
        free(pAdminAccount);
    }
    
    return 0;
}

Remarque: je n'ai pas fait de C depuis des lustres, alors vérifiez ce que j'explique ici.

Explication:

Il existe donc différentes manières d'utiliser une structure.

La première façon d'utiliser est comme tout autre type tel que int, char, bool, etc.

Si je fais int a; a = 4; , la mémoire de la pile est fournie qui sera disponible dans le bloc qu'elle a déclaré. Donc, si vous le créez dans une fonction, il sera disponible jusqu'à ce que vous quittiez la fonction, même si vous renvoyez l'adresse de cette variable en utilisant & . Ne fais pas ça.

Donc, struct Account userAccount; créera une variable que vous pourrez utiliser immédiatement: userAccount.acct_year = 4;

Si vous souhaitez accéder indirectement à l'aide d'un pointeur, vous devez créer un pointeur struct Account *pUserAccount; . Dans ce pointeur, c'est là que nous enregistrons l'adresse de userAccount de cette manière: pUserAccount = &userAccount . Remarques que je n'ai pas utilisé le * car nous n'y accédons pas.

L'avantage d'utiliser cette méthode est que le compilateur connaît la taille de ce que nous pointons. Plus tard, lorsque vous serez familiarisé avec cela, vous pourrez jouer avec un tableau de structures et comment y accéder à l'aide de pointeurs.

Quoi qu'il en soit, continuez avec l'explication.

Si vous souhaitez par exemple avoir une fonction qui crée un compte et utilise un tel compte en dehors d'une fonction, alors vous devez utiliser malloc . malloc récupère la mémoire du tas et renvoie une adresse à cet emplacement mémoire.

Vous devez indiquer à malloc la quantité de mémoire que vous souhaitez réserver: sizeof (struct Account) .

Comme expliqué, malloc(sizeof (struct Account)); renverra une adresse. Maintenant, vous pouvez renvoyer cette adresse depuis votre fonction ou l'utiliser tout de suite.

Il est important que vous vérifiiez NULL car malloc pourrait ne pas obtenir de mémoire de réserve (c'est-à-dire manquer de mémoire).

En outre, il est important pour vous de nettoyer après vous-même. Libérez la mémoire que vous avez prise dans le tas afin que d'autres programmes puissent également l'utiliser. Cela évitera de nombreux problèmes tels que la segmentation de la mémoire et autres.

Vous pouvez le déclarer comme struct Account userAccount; et automatiquement la mémoire sera allouée pendant toute la durée de vie du bloc. Si la déclaration du


5 commentaires

et nous pouvons utiliser le pointeur pour struct comme un tableau correct? merci mec, ça a beaucoup de sens


@JohnDoe, oui; cependant, soyez conscient. Le pointeur pointera vers le début du tableau de structures. Par conséquent, lors de l'itération dans tout le tableau, il est courant d'utiliser deux pointeurs. Un pointeur continue de pointer vers le début du tableau et le deuxième pointeur est utilisé pour itérer. En supposant que pArrayStructs pointe vers le début du tableau, pArrayStructs++ irait à l'élément suivant du tableau. Si la réponse vous a aidé, n'oubliez pas de l'indiquer. :)


deux pointeurs? Je vais devoir regarder un tutoriel à ce sujet, mais comment indiquer la réponse?


@JohnDoe Oui. Pensez-y. Disons que vous n'avez qu'un seul pointeur vers un tableau de structures dans la mémoire du tas. Vous incrémentez ce pointeur plusieurs fois pour accéder aux éléments. Si vous ne renvoyez pas le pointeur à son adresse d'origine, lorsque vous essayez une opération telle que l'utilisation de free(your_pointer_here) pour libérer la mémoire que vous utilisiez, la fonction free démarrera du mauvais endroit. Le plus sûr, vous obtiendrez une erreur de segmentation ou d'accès à la mémoire auquel vous ne devriez pas accéder.


@JohnDoe en haut de ma réponse, il y a un nombre (actuellement en 0) avec une flèche vers le haut au-dessus et une flèche vers le bas en dessous. Appuyez sur la flèche vers le haut au-dessus du 0 si vous pensez que la réponse correspond à ce que vous espériez.



0
votes

Vous avez deux options pour initialiser un pointeur déclaré. Prenons votre exemple:

int main (void)
{
    account *accountant = malloc (sizeof *accountant);  /* allocate for 1 account */
    
    if (accountant == NULL) {                           /* validate every allocation */
        perror ("malloc-accountant");
        return 1;
    }
    
    strcpy (accountant->name, "Client A");
    accountant->acct_year = 2019;
    
    /* use accountant as needed */
    printf ("\naccountant: %s (%d)\n", accountant->name, accountant->acct_year);

    free (accountant);                                 /* free what you allocate */
}

Ci-dessus, accountant est un pointeur non initialisé qui contient une adresse indéterminée (qui peut être n'importe quoi) comme valeur. Pour initialiser le pointeur, vous devez soit (1) lui attribuer l'adresse d'un account type existant, par exemple

int main (void)
{
    account account1 = { "Client A", 2019 };     /* object of type account */
    account *accountant = &account1;             /* address assigned to pointer */
    
    /* use accountant as needed */
    printf ("\naccountant: %s (%d)\n", accountant->name, accountant->acct_year);
}

Ou, (2) allouer dynamiquement du stockage pour le accountant avec malloc , calloc ou realloc , par exemple

typedef struct account {
    char name[80];
    int acct_year;
} account;

int main (void)
{
    account *accountant;
}

Dans les deux cas, c'est bien. Un pointeur est simplement une variable normale qui contient l' adresse où quelque chose d'autre est stocké en mémoire comme sa valeur. En d'autres termes, un pointeur pointe vers l'adresse où quelque chose d'autre peut être trouvé. Vous devez vous assurer que l'adresse que le pointeur contient car sa valeur pointe vers une adresse mémoire valide contenant un objet de ce type. Si vous demandez toujours "Où pointe mon pointeur?" avant de l'utiliser - vous n'aurez plus jamais de problèmes avec les pointeurs.


0 commentaires