web-dev-qa-db-fra.com

Comment puis-je passer directement à une position de pointeur sans utiliser l'opérateur ++?

Je travaille avec un pointeur sur une structure. Je veux savoir s'il est possible de passer directement à une position spécifique sans utiliser l'opérateur ++

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

#define ARRAY_SIZE 10

struct dummy{
    int id;
    char buffer[10];
};

typedef struct dummy dummy_struct;

int main()
{
    int i=0;
    dummy_struct *ds = malloc(sizeof(dummy_struct)*ARRAY_SIZE);
    dummy_struct *iterator = ds;

    for(i=0;i<ARRAY_SIZE;i++)
    {
        iterator->id = i;
        sprintf(iterator->buffer,"%d",i);
        iterator++;
    }

    iterator = ds;

    for(i=0;i<ARRAY_SIZE;i++)
    {
        printf("%d:%s:%p\n",iterator->id,iterator->buffer,iterator);
        iterator++;
    }

    // I want to access directly to 5th position
    iterator = ds + (sizeof(dummy_struct)*5);
    printf("5th position %d:%s:%p\n",iterator->id,iterator->buffer,iterator);

    return 0;
}

Cette déclaration

iterator = ds + (sizeof(dummy_struct)*5);

ne fonctionne pas. J'apprécierai n'importe quelle suggestion.

9
Rubén Pozo

Eh bien, l'arithmétique de pointeur honore le type de données !!

iterator = ds + 5;

va faire le travail.

Pour élaborer, l'expression ci-dessus produira un pointeur en le déplaçant 5 fois, multiplié par la taille du type pour ds, en octets. C'est la même chose que &(ds[5]).

Par souci d’exhaustivité, expliquer pourquoi iterator = ds + (sizeof(dummy_struct)*5); est erroné, c’est, ici, que vous essayez essentiellement de déplacer le pointeur sur un élément dont l’index est (sizeof(dummy_struct)*5, ce qui est bien hors limites. Notez s'il vous plaît, cela appelle un comportement non défini !! note ci-dessous

Citer C11, chapitre §6.5.6/P8

Lorsqu'une expression de type entier est ajoutée ou soustraite à un pointeur, le result a le type de l'opérande de pointeur. Si l'opérande du pointeur pointe vers un élément de un objet tableau, et le tableau est assez grand, le résultat pointe vers un élément décalé par rapport à l'élément d'origine tel que la différence entre les indices du résultat et de l'original les éléments du tableau sont égaux à l'expression entière. En d'autres termes, si l'expression P pointe sur i- ème élément d'un objet tableau, les expressions (P)+N (de manière équivalente, N+(P)) et (P)-N (où N a la valeur n) pointez sur, respectivement, les éléments i+n- th et i−n- th de l'objet tableau, à condition qu'ils existent. [....]

et puis, en ce qui concerne le comportement indéfini mentionné ci-dessus, 

[....] Si à la fois le pointeur l’opérande et le résultat pointent sur des éléments du même objet de tableau, ou un au-delà du dernier élément de l'objet tableau, l'évaluation ne doit pas produire de dépassement de capacité; sinon, le le comportement est indéfini. Si le résultat pointe un après le dernier élément de l'objet tableau, il ne doit pas être utilisé comme opérande d'un opérateur unaire * évalué.


Cela étant dit, la déclaration printf() est également erronée. Vous avez deux spécificateurs de conversion, mais trois arguments fournis. Ce n'est pas nuisible, mais inutile/sans signification.

À ce sujet, du chapitre §7.21.6.1/P2,

[...] Si le format est épuisé tant qu'il reste des arguments, les arguments en excès sont évalué (comme toujours) mais sont autrement ignorés. [...]

Sur la base de ce cas, vous pouvez directement utiliser

printf("5th position %d:%s:\n",ds[5].id,ds[5].buffer);
30
Sourav Ghosh

Le comportement de 

iterator = ds + (sizeof(dummy_struct) * 5);

est undefined si vous définissez un pointeur au-delà du dernier élément du tableau. Vous définissez en fait iterator à d'autres éléments du tableau que vous ne le pensez, par un facteur de sizeof(dummy_struct)! Ne fais pas ça.

La langue vous permet d’utiliser la notation iterator = ds + 5;. Cette arithmétique idiomatique pointeur ajoute 5 beaucoup de sizeof(dummy_struct) à l'adresse iterator. En d'autres termes, le compilateur effectue l'ajustement sizeof pour vous. C'est l'une des raisons pour lesquelles l'arithmétique des pointeurs est si puissante.

Notez enfin que *(ds + 5) est équivalent à ds[5]. Je trouve que ce dernier offre plus de clarté lorsque vous travaillez avec des tableaux.

8
Bathsheba

On dirait que vous essayez de faire en sorte que le pointeur iterator pointe sur l'élément 5th du tableau ds. Mais cette déclaration vous donnera un résultat erroné:

iterator = ds + (sizeof(dummy_struct)*5);

Le résultat de sizeof(dummy_struct)*5 donnera la taille totale de tous les éléments de la structure dummy_struct multipliée par 5, qui sera ajoutée à l'adresse référencée par ds et assignée à iterator. Donc, la variable iterator peut pointer sur un emplacement mémoire que votre programme ne possède pas. Tu as besoin de faire:

iterator = ds + 5;

Ou vous pouvez aussi faire:

iterator = &ds[5];
2
H.S.