recherche

Maison  >  Questions et réponses  >  le corps du texte

objective-c - 关于C语言指针的问题

C语言指针问题 下面代码为什么第二个数字是5呢?

int a[5] = {1,2,3,4,5};
int *p = (int *)(&a+1);
NSLog(@"%d,%d", *(a+1), *(p-1));
黄舟黄舟2769 Il y a quelques jours428

répondre à tous(3)je répondrai

  • 阿神

    阿神2017-04-21 11:19:34

    &a donne un pointeur vers le tableau, donc &a+1 se déplace en fait en fonction de la longueur du tableau. Si vous souhaitez simplement obtenir le deuxième élément du tableau, utilisez *(&a[0]+1), car le type de données de &a[0] est int*. Dessinez d’abord une image :

    Supposons que nous ayons le tableau suivant

    int a[5] = {1,2,3,4,5};
    int *x = &a+1;
    

    Bien que le programme ci-dessus puisse être compilé et transmis, le compilateur émettra un avertissement car les types de x et a ne correspondent pas. Il existe deux façons de supprimer l'avertissement

    .

    1. Par conversion de type forcée

    int *x = (int *)(&a+1); 
    print("%d\n",*(x-1));
    

    2. Trouvez un type approprié pour cela. Le type de &a est int (*)[5]

    int (*x)[5] = &a+1;
    printf("%d\n",**(x-1));
    

    Cela implique comment écrire les types de données appropriés, ce qui est très important dans l'affectation et le passage des paramètres !

    Donc, je dois d'abord résumer les types de données de a, &a et &a[0]

    1. a est le nom du tableau, qui est le pointeur vers le premier élément du tableau Il ne fait aucun doute qu'ici, le type de données du premier élément du tableau est int, donc. le type de données de a est int*.

    2. &a prend l'adresse d'un tableau unidimensionnel, et le résultat est un pointeur vers le tableau (dans ce cas, un pointeur vers un tableau de int), c'est-à-dire

      int(*)[5 ] .

    3. &a[0] est très simple. Tout d'abord, a[0] obtient un entier, puis en prend l'adresse, donc son type de données est

      int*.

    Maintenant que vous connaissez le type de données, l'arithmétique du pointeur devient beaucoup plus claire !

    Regardez d'abord la partie du code qui réussit la conversion de type forcée. Quel nombre va-t-il afficher ?

    La réponse est 5 ! D'après le résumé des types de données de tout à l'heure, nous pouvons savoir que le type de données de &a est

    int (*)[5], donc &a+1 a en fait été déplacé de 5*sizeof(int) octets Maintenant, le pointeur pointe vers l'élément après le dernier élément du tableau (Figure 1), c'est-à-dire qu'il a franchi la frontière ! Mais parce que le type de données de x est en fait int * Donc pour x-1, il est en fait déplacé de 1*sizeof(int) octets vers la gauche, ce qui signifie qu'il pointe vers le dernier élément, donc *(x-1) est obtenu La valeur est le dernier élément du tableau : 5

    D'accord, regardons maintenant la deuxième partie. Quel nombre cela produira-t-il ? Ne parlons pas d’abord de la réponse. Je viens de le dire ici. Le type de données de Sizeof(int)*5 octets sont déplacés en unités, donc x-1 est en fait déplacé vers la gauche de sizeof(int)*5 octets. Il est déplacé sur ma machine. 20 octets, ce qui revient au premier élément du tableau, donc la réponse est : 1

    Ce qui précède est un tableau à une dimension. Maintenant, je veux parler de la situation d'un tableau à deux dimensions. Il y a le morceau de code suivant :

    int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    /*
    ?? = a; // int (*b)[3] = a;
    ?? = a[0]; // int *c = a[0];
    ?? = a[0][0] // int d = a[0][0];
    ?? = &a; // int (*e)[3][3] = &a;
    ?? &a[0]; // int (*f)[3] = &a[0]
    ?? &a[0][0]; // int *g = &a[0][0]
    */
    

    Examinons d'abord les types de données de a, a[0], &a, &a[0], &a[0][0] :

    Faites attention au texte en gras ci-dessus. Le nom du tableau est un pointeur vers le premier élément du tableau !

    1. Quel est le type de données d'un ? ? int * ? Non, le cœur de ce texte en gras sont les cinq mots le premier élément. Le premier élément de a n'est-il pas simplement a[0][0] ? À proprement parler, non, le premier élément de a est en fait a[0], alors quel est le type de données de a[0] ? un[0] est un tableau contenant trois éléments int, donc le type de a[0] est le même que le type de t dans int t[3], qui est int* Depuis le type de données du premier élément. est int*, si ce tableau à deux dimensions est considéré comme un tableau à une dimension, il s'agit en fait d'un tableau contenant trois éléments int*. Un tableau est un tableau de pointeurs, donc le type de données de a est int (*)[3]

    2. Regardons à nouveau &a. Comme mentionné en parlant de tableaux unidimensionnels, l'adresse obtenue en prenant l'adresse d'un nom de tableau est un pointeur vers le tableau, donc le type de données de &a est int (*)[3] [3]

    3. &a[0] Cela semble un peu pénible, mais comme mentionné dans le paragraphe précédent, a[0] est un tableau contenant trois éléments int, et int t[3] Le type de données de t est le même, qui est int* Naturellement, le type de données de &a[0] est le même que le type de données de &t, c'est-à-dire int (*) [3]

    À ce stade, nous avons presque écrit sur le type de données dans le tableau bidimensionnel. Maintenant que nous connaissons le type de données, nous pouvons savoir avec précision où le pointeur se déplacera après le calcul !

    Regardez le code suivant :

    int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    int (*x)[3] = a;
    int *k = a[0];
    int (*y)[3][3] = &a;
    int (*q)[3] = &a[0];
    int *z = &a[0][0];
    
    printf("%d\n",(*(x+1))[0]);
    printf("%d\n",*(k+1));
    printf("%d\n",(*(*(y+1)))[0]);
    printf("%d\n",(*(q+1))[0]);
    printf("%d\n",*(z+1));
    
    int *p = (int *)(y+1);
    printf("%d\n",*(p-1));
    
      Le type de données de
    • x est int (*)[3], donc x+1 est en fait déplacé de 3*sizeof(int) octets, comme le montre la figure :

    • Le type de données de
    • k est int *, donc k+1 est en fait déplacé de sizeof(int) octets.

    • Le type de données de
    • y est int (*)[3][3], donc y+1 est en fait déplacé de 3*3*sizeof(int) octets, ce qui correspond au dernier du tableau L'élément après l'élément. Comme le montre l'image :

    • Le type de données de
    • q est int (*)[3], donc q+1 est en fait déplacé de 3*sizeof(int) octets.

    • Le type de données de
    • z est int *, donc z+1 est en fait déplacé de sizeof(int) octets.

    Ainsi, lors de l'ajout et de la soustraction de pointeurs de tableau, la chose la plus importante est de connaître la taille de son pas, et la taille du pas est déterminée par le type de données !

    répondre
    0
  • PHP中文网

    PHP中文网2017-04-21 11:19:34

    La personne qui a répondu au premier étage a très bien écrit, veuillez développer

    La valeur du pointeur est l'adresse d'un tableau
    int (* pa)[5];
    pa++;pa recule de 20 octets (5*4)

    Contraste, les éléments du tableau sont des pointeurs (int*)
    int *pa[5];
    pa++;pa recule de 4 octets

    répondre
    0
  • 高洛峰

    高洛峰2017-04-21 11:19:34

    Désolé de reposter un ancien message. J'ai vu cela accidentellement, car dans le passé, lorsque je faisais de la programmation embarquée, des tableaux et des pointeurs étaient souvent utilisés, y compris l'attribution directe d'une adresse mémoire à la variable de pointeur (cela n'est généralement pas utilisé dans les applications normales), et je n'avais jamais trouvé &arr avant. Quelle est la différence avec arr. J'ai vérifié spécifiquement aujourd'hui et découvert que cela dépend du compilateur. Certains compilateurs traitent les tableaux et les pointeurs séparément. La signification de prendre une adresse pour un nom de tableau concerne la mémoire entière du tableau. Certains compilateurs considèrent le tableau comme une forme spécifique de pointeur. Dans ce cas, le pointeur saute d'un point. élément de mémoire du tableau, mais la mémoire du tableau entière n'existe pas.

    répondre
    0
  • Annulerrépondre