Opérateur de flèche ( - > ) utilisation en C
J'apprends actuellement C en lisant un bon livre de débutant intitulé "Teach Yourself C in 21 Days" (J'ai déjà appris Java et C# donc je me déplace à un rythme beaucoup plus rapide). Je lisais le chapitre sur les pointeurs et l'opérateur -> (flèche) est apparu sans explication. Je pense qu'il est utilisé pour appeler les membres et les fonctions (comme l'équivalent de la . (dot) opérateur, mais pour les pointeurs au lieu de membres). Mais je ne suis pas entièrement sûr. Je peux avoir une explication et un code l'échantillon?
11 réponses
foo->bar
est équivalent à (*foo).bar
, c'est à dire qu'il obtient le membre appelé bar
de la structure que foo
points.
Oui, c'est ça.
C'est juste la version dot lorsque vous voulez accéder aux éléments d'une structure/classe qui est un pointeur au lieu d'une référence.
struct foo
{
int x;
float y;
};
struct foo var;
struct foo* pvar;
var.x = 5;
(&var)->y = 14.3;
pvar->y = 22.4;
(*pvar).x = 6;
C'est ça!
a->b
est juste un peu juste pour (*a).b
dans tous les sens (même pour les fonctions: a->b()
" est l'abréviation de (*a).b()
).
foo->bar
est seulement un raccourci pour (*foo).bar
. C'est tout là est à lui.
Je voudrais juste ajouter aux réponses le " pourquoi?".
.
est un opérateur d'accès de membre standard qui a une priorité supérieure à l'opérateur de pointeur *
.
Lorsque vous essayez d'accéder aux internes d'une structure et que vous l'avez écrit comme *foo.bar
alors le compilateur penserait à vouloir un élément 'bar' de 'foo' (qui est une adresse en mémoire) et évidemment cette simple adresse n'a pas de membres.
Ainsi, vous devez demander au compilateur de première déréférencement avec (*foo)
, puis accéder à l' élément membre: (*foo).bar
, ce qui est un peu maladroit à écrire donc les bons gens ont mis au point une version abrégée: foo->bar
qui est une sorte d'accès membre par l'opérateur de pointeur.
struct Node {
int i;
int j;
};
struct Node a, *p = &a;
Ici pour accéder aux valeurs de i
et j
on peut utiliser la variable a
et le pointeur p
comme suit: a.i
, (*p).i
et p->i
sont tous les mêmes.
Ici .
est un "Direct Sélecteur" et ->
est un "Indirecte Sélecteur".
J'ai dû faire un petit changement au programme de Jack pour le faire fonctionner. Après avoir déclaré le pointeur struct pvar, pointez-le vers l'adresse de var. J'ai trouvé cette solution à la page 242 de la programmation de Stephen Kochan en C.
#include <stdio.h>
int main()
{
struct foo
{
int x;
float y;
};
struct foo var;
struct foo* pvar;
pvar = &var;
var.x = 5;
(&var)->y = 14.3;
printf("%i - %.02f\n", var.x, (&var)->y);
pvar->x = 6;
pvar->y = 22.4;
printf("%i - %.02f\n", pvar->x, pvar->y);
return 0;
}
Exécutez ceci dans vim avec la commande suivante:
:!gcc -o var var.c && ./var
Affichera:
5 - 14.30
6 - 22.40
#include<stdio.h>
int main()
{
struct foo
{
int x;
float y;
} var1;
struct foo var;
struct foo* pvar;
pvar = &var1;
/* if pvar = &var; it directly
takes values stored in var, and if give
new > values like pvar->x = 6; pvar->y = 22.4;
it modifies the values of var
object..so better to give new reference. */
var.x = 5;
(&var)->y = 14.3;
printf("%i - %.02f\n", var.x, (&var)->y);
pvar->x = 6;
pvar->y = 22.4;
printf("%i - %.02f\n", pvar->x, pvar->y);
return 0;
}
L'opérateur ->
rend le code plus lisible que l'opérateur *
dans certaines situations.
Tels que: (Cité du projet EDK II )
typedef
EFI_STATUS
(EFIAPI *EFI_BLOCK_READ)(
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
OUT VOID *Buffer
);
struct _EFI_BLOCK_IO_PROTOCOL {
///
/// The revision to which the block IO interface adheres. All future
/// revisions must be backwards compatible. If a future version is not
/// back wards compatible, it is not the same GUID.
///
UINT64 Revision;
///
/// Pointer to the EFI_BLOCK_IO_MEDIA data for this device.
///
EFI_BLOCK_IO_MEDIA *Media;
EFI_BLOCK_RESET Reset;
EFI_BLOCK_READ ReadBlocks;
EFI_BLOCK_WRITE WriteBlocks;
EFI_BLOCK_FLUSH FlushBlocks;
};
La structure _EFI_BLOCK_IO_PROTOCOL
contient 4 membres de pointeur de fonction.
Supposons que vous ayez une variable struct _EFI_BLOCK_IO_PROTOCOL * pStruct
, et que vous souhaitiez utiliser le bon vieux opérateur *
pour appeler son pointeur de fonction membre. Vous finirez avec du code comme ceci:
(*pStruct).ReadBlocks(...arguments...)
Mais avec l'opérateur ->
, vous pouvez écrire comme ce:
pStruct->ReadBlocks(...arguments...)
.
Qui semble mieux?
Dot est un opérateur de déréférence et utilisé pour connecter la variable de structure pour un enregistrement particulier de structure. Par exemple:
struct student
{
int s.no;
Char name [];
int age;
} s1,s2;
main()
{
s1.name;
s2.name;
}
De cette manière, nous pouvons utiliser un opérateur de point pour accéder à la variable de structure
#include<stdio.h>
struct examp{
int number;
};
struct examp a,*b=&a;`enter code here`
main()
{
a.number=5;
/* a.number,b->number,(*b).number produces same output. b->number is mostly used in linked list*/
printf("%d \n %d \n %d",a.number,b->number,(*b).number);
}
La sortie est 5 5 5