1
votes

Pointeur vers un type de tableau (types personnalisés)

J'ai un type de tableau personnalisé défini comme dans le code et un pointeur vers ce type de tableau également défini. J'essaie de trouver une corrélation entre le type de tableau personnalisé et un pointeur vers le type de tableau personnalisé. Comment attribuer une valeur au pointeur du type de tableau personnalisé afin de pouvoir parcourir le tableau à l'aide du pointeur?

#include<stdio.h>

typedef int array_type[3];
typedef array_type* ptr_array_type;

int main() {
   array_type a = {2,3,4};
   ptr_array_type ptr;

   ptr = a;

   printf("%d\n",*ptr);

}

Je sais que le nom du tableau contient le pointeur vers le premier élément. Je reçois toujours une impression invalide: -50204788 au lieu de 2.

Je reçois également un avertissement:

avertissement: affectation à 'ptr_array_type' {aka 'int (*) [3]'} à partir d'un type de pointeur incompatible ' int * '[-Wincompatible-pointer-types] ptr = a;

Quelqu'un pourrait-il m'indiquer la bonne manière d'attribuer une valeur appropriée au pointeur afin que je puisse parcourir le tableau.


4 commentaires

Ne cachez pas la nature du pointeur derrière un typedef. C'est beaucoup plus enclin à dérouter (les gens) qu'à aider.


Vous affectez le type T à la variable T * . Ceux-ci sont incompatibles. Et le fait que T soit un tableau ne le change pas.


Le type de * ptr est int [3] . Cela se décompose en un pointeur vers le premier élément, ce qui n'est pas du tout équivalent à la valeur de du premier élément.


Le code provient en fait d'un projet autosar où les types sont définis comme cela, et maintenant j'essaie de comprendre comment ils sont affectés.


3 Réponses :


1
votes

ptr est un pointeur vers int [3] ; a est un int [3] . Bien que je n'aime pas les types de pointeurs typedef en général, si vous insistez sur cette approche, voici comment vous pouvez déréférencer le premier élément de a de ptr :

ptr = &a;
printf("%d\n", **ptr);


2 commentaires

Merci pour la réponse, pourriez-vous expliquer la solution un peu plus en détail. Merci d'avance.


Dans le code, je ne comprends pas le premier typedef pour le type de tableau. Comment cela peut-il être écrit sans dactylographier?



2
votes

Comment attribuer une valeur au pointeur du type de tableau personnalisé afin que je peut-il parcourir le tableau en utilisant le pointeur?

Étant donné le array_type défini par

printf("%d\n", *p++);
printf("%d\n", *p++);
printf("%d\n", *p++);

, le type de pointeur auquel vous pouvez attribuer un array_type est int * :

assert(*p == 2);

Vous pouvez (apparemment) attribuer un objet de array_type à un pointeur de type ptr_array_element :

array_type a = {2, 3, 4};
ptr_array_element p = a;

Ceci fait, vous pouvez accéder au premier élément du tableau via l'opérateur de dérférence.

typedef int *ptr_array_element;

Et vous pouvez généralement l'utiliser un peu comme un itérateur C ++:

typedef int array_type[3];

MAIS NE PAS.

Utilisez les typedefs avec parcimonie , où ils cachent des détails non pertinents, améliorent considérablement la clarté du code, ou similaire. Évitez d'utiliser des typedefs qui obscurcissent les détails pertinents , tels que le fait que les objets de ce type sont des pointeurs ou des tableaux, à moins que, éventuellement, ces détails soient parfaitement clairs dans les noms de type, ou à moins que les masquer ne soit intentionnel et inoffensif. Il est rarement inoffensif de masquer la nature du tableau ou du pointeur.


0 commentaires

0
votes

ptr_array_type alias int (*) [3] , et non int * - vous ne pourrez pas l'utiliser pour parcourir array_type . Vous pourriez l'utiliser pour parcourir un tableau de array_type , comme ceci:

 array_type *arr = new_array_type( 1, 2, 3 );  // even this is leaky since it assumes we know
                                               // the array element type is integral
 array_type_iterator *itr = new_array_type_iterator( arr );
 array_element_type target;

 begin_iterator( &itr ); 
 while( next_iterator( &itr ) )
 {
   get_data_from_iterator( itr, &target );
   write_array_element_to( stdout, target );
 }

 free_array_type_iterator( itr );
 free_array_type( arr );

Si vous le souhaitez pour pouvoir parcourir un tableau de T avec un pointeur, alors le type de ce pointeur doit être T * . Vous devez donc changer vos typedefs en quelque chose comme

typedef int array_type[3];    // probably want to replace int with another
typedef int *ptr_array_type;  // typedef to abstract out the type
...
array_type a = {1, 2, 3}; // yuck! don't do this! a is not obviously an array,
                          // so an array initializer looks wrong in this context
ptr_my_type p = a;

printf( "%d", *p );

Cependant ...

Si vous utilisez typedef code > pour faire abstraction des détails d'implémentation pour un type, vous devez alors abstraire tous les détails d'implémentation pour ce type, y compris des choses comme le déréférencement et l'indexation. Vous voudrez créer une API complète, telle que:

array_type arr[3];
ptr_array_type ptr = arr;

while ( size_t i = 0; i < 3; i++ )
  do_something_with( ptr[i] );

Les abstractions partielles ou qui fuient conduisent simplement à un code déroutant à utiliser et à maintenir. Si l'utilisateur d'un type doit être conscient du "array-ness" ou du "pointer-ness" de ce type pour l'utiliser correctement, alors ne cachez pas ces qualités derrière un typedef sans fournir des remplacements pour le [ ] et les opérateurs unaires * également. Fournissez également un moyen d'abstraire les E / S - ne forcez pas l'utilisateur à savoir s'il doit utiliser % d ou % f ou % s dans une instruction printf s'ils ne fonctionnent pas avec un type primitif.


0 commentaires