web-dev-qa-db-fra.com

Comment fonctionne la comparaison de pointeurs en C? Est-il correct de comparer des pointeurs qui ne pointent pas vers le même tableau?

Dans K&R (The C Programming Language 2nd Edition) chapitre 5, je lis ce qui suit:

Premièrement, les pointeurs peuvent être comparés dans certaines circonstances. Si p et q pointent vers des membres du même tableau, alors des relations comme ==, !=, <, >=, etc. fonctionnent correctement.

Ce qui semble impliquer que seuls les pointeurs pointant vers le même tableau peuvent être comparés.

Mais quand j'ai essayé ce code

    char t = 't';
    char *pt = &t;
    char x = 'x';
    char *px = &x;

    printf("%d\n", pt > px);

1 est imprimé à l'écran.

Tout d'abord, je pensais obtenir un type non défini ou un type ou une erreur, car pt et px ne pointent pas vers le même tableau (du moins à ma connaissance).

Est également pt > px parce que les deux pointeurs pointent vers des variables stockées dans la pile et que la pile se développe, donc l'adresse mémoire de t est supérieure à celle de x? C'est pourquoi pt > px est vrai?

Je suis plus confus lorsque malloc est introduit. Également dans K&R au chapitre 8.7, ce qui suit est écrit:

Il y a cependant une hypothèse, cependant, que les pointeurs vers différents blocs renvoyés par sbrk peuvent être comparés de manière significative. Ceci n'est pas garanti par la norme qui permet des comparaisons de pointeurs uniquement dans un tableau. Ainsi, cette version de malloc n'est portable que parmi les machines pour lesquelles la comparaison générale des pointeurs est significative.

Je n'ai eu aucun problème à comparer les pointeurs pointant vers l'espace malloculé sur le tas aux pointeurs pointant vers des variables de pile.

Par exemple, le code suivant a bien fonctionné, avec 1 en cours d'impression:

    char t = 't';
    char *pt = &t;
    char *px = malloc(10);
    strcpy(px, pt);
    printf("%d\n", pt > px);

Sur la base de mes expériences avec mon compilateur, je suis amené à penser que n'importe quel pointeur peut être comparé à n'importe quel autre pointeur, indépendamment de l'endroit où ils pointent individuellement. De plus, je pense que l'arithmétique des pointeurs entre deux pointeurs est correcte, peu importe où ils pointent individuellement, car l'arithmétique utilise simplement les adresses de mémoire stockées par les pointeurs.

Pourtant, je suis confus par ce que je lis dans K&R.

La raison pour laquelle je demande, c'est parce que mon prof. en fait une question d'examen. Il a donné le code suivant:

struct A {
    char *p0;
    char *p1;
};

int main(int argc, char **argv) {
    char a = 0;
    char *b = "W";
    char c[] = [ 'L', 'O', 'L', 0 ];

   struct A p[3];
    p[0].p0 = &a;
    p[1].p0 = b;
    p[2].p0 = c;

   for(int i = 0; i < 3; i++) {
        p[i].p1 = malloc(10);
        strcpy(p[i].p1, p[i].p0);
    }
}

Qu'est-ce que cela évalue:

  1. p[0].p0 < p[0].p1
  2. p[1].p0 < p[1].p1
  3. p[2].p0 < p[2].p1

La réponse est 0, 1, et 0.

(Mon professeur inclut l'avertissement sur l'examen que les questions sont pour un environnement de programmation Ubuntu Linux 16.04, version 64 bits)

(note de l'éditeur: si SO permettait plus de balises, cette dernière partie justifierait x86-64 , linux , et peut-être Assembly . Si le point de la question/classe était spécifiquement les détails d'implémentation du système d'exploitation de bas niveau, plutôt que C. portable)

33
Shisui

C'est simple: comparer des pointeurs n'a pas de sens car les emplacements de mémoire des objets ne sont jamais garantis dans le même ordre que vous les avez déclarés. L'exception est les tableaux. & array [0] est inférieur à & array [1]. C'est ce que K&R souligne. Dans la pratique, les adresses des membres struct sont également dans l'ordre où vous les déclarez dans mon expérience. Aucune garantie à ce sujet .... Une autre exception est si vous comparez un pointeur pour égal. Lorsqu'un pointeur est égal à un autre, vous savez qu'il pointe vers le même objet. Peu importe ce que c'est. Mauvaise question d'examen si vous me demandez. Selon Ubuntu Linux 16.04, environnement de programmation de version 64 bits pour une question d'examen? Vraiment ?

0
Hans Lepoeter