IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Bizarreries du langage C


Sujet :

C

  1. #21
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Par défaut
    Je tombe des nues. Je savais pas que ce genre de chose était compilable :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int main ()
    {
        int a [5] ;
        int b = 2 ;
        3[a] = 3 ;
        b[a] = 1 ;
        a[2][a] = 5 ;
        return 0 ;
    }
    Bizarre, toutes ces syntaxes. J'ai jamais vu ça dans la norme C.

  2. #22
    Membre éprouvé
    Inscrit en
    Juin 2008
    Messages
    91
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 91
    Par défaut
    Citation Envoyé par jeroman Voir le message
    Bizarre, toutes ces syntaxes. J'ai jamais vu ça dans la norme C.
    C'est une conséquence de l'équivalence entre : a[i] et *((a) + (i)) donc avec *((i) + (a)) d'où i[a].

    J'ai toujours été sceptique quant à ça, mais malheureusement pour moi je ne suis pas encore tombé sur un compilateur qui rejette ça.

    D'ailleurs il serait intéressant de savoir dans quel cas cela planterait, si quelqu'un veut bien partager son savoir à ce sujet .

  3. #23
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 851
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 851
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par uknow Voir le message
    D'ailleurs il serait intéressant de savoir dans quel cas cela planterait, si quelqu'un veut bien partager son savoir à ce sujet .
    On ne peut jamais savoir quand ça plantera, quoi qu'on écrive.
    La règle est simple: si ce qu'on écrit est correct (qu'on ne dépasse pas la zone allouée, qu'on n'utilise pas un pointeur non initialisé, etc etc etc) alors le programme se déroule correctement.
    En revanche si ce qu'on écrit n'est pas correct, alors (en dehors des cas bateau comme division par 0) on a un comportement indéterminé => non prévisible (dans la plus large acceptation de ce que ce terme signifie) => ça peut éventuellement planter mais rien ne le garantit.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #24
    Membre éprouvé
    Inscrit en
    Juin 2008
    Messages
    91
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 91
    Par défaut
    C'est évident, mais l'expression 3[a] ne cache-t-elle pas derrière elle un comportement indéterminé ou dépendant de l'implémentation ?

    Surtout qu'on n'a pas la certitude qu'un pointeur a une valeur numérique, et que a[3] sera automatiquement convertie en *((a) + (3)) (on a la certitude que les deux expressions sont équivalentes par la norme mais pas que l'une est ramenée automatiquement à l'autre).

    Autrement dit, si a[3] est garantie être ramenée à *((a) + (3)) alors oui effectivement il n'y a pas de soucies à se faire pour 3[a] (grâce à l'arithmétique des pointeurs).

  5. #25
    Membre averti
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 55
    Par défaut
    a[2][a] = 5;
    J'aime beaucoup!

    Tout comme l'exemple du swap, c'est original. Bien que je trouve que celui-ci n'ait rien d'étrange, ou d'inconnu. Vu qu'il s'agit simplement d'opération binaire répétée ^^

    @uknow
    Il me semble bien que la norme spécifie aussi le fait que:
    tab[x] <=> x[tab]

    Il n'y a donc pour moi pas de comportement indéterminé ici.

    EDIT:
    1) Je sais pas qui a voté pour la conversation, mais c'est chouette.
    En espérant avoir plein d'autres exemples!

    2) Sinon, oui le but de ma conversation est d'obtenir des syntaxes étranges, inconnues...
    Et pas d'avoir du code illisible, ca c'est pas trop dur!

  6. #26
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    @uknow :
    Autrement dit, si a[3] est garantie être ramenée à *((a) + (3)) alors oui effectivement il n'y a pas de soucies à se faire pour 3[a] (grâce à l'arithmétique des pointeurs).
    C'est absolument garanti : la norme définit l'opérateur [] par la propriété "a[b] est identique à (*((a)+(b)))"

  7. #27
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Peut-on classer ceci comme une étrangeté ?

    Dans certains cas, l'expression a+b-c est rejetée par le compilateur alors que a-c+b esr acceptée.
    Pourquoi ?


    (Experts du langage, abstenez-vous de répondre, ce ne serait pas du jeu)

  8. #28
    Membre averti
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 55
    Par défaut
    Dans certains cas, l'expression a+b-c est rejetée par le compilateur alors que a-c+b esr acceptée.
    Peux tu préciser, les certains cas dont tu parles? Ou en donner un?

    Car normalement les opérateurs '+' et '-', ont la même priorité.
    Je ne vois donc pas de raison pour lesquels ceci serait incorrect.

  9. #29
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 851
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 851
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ugo188 Voir le message
    Peux tu préciser, les certains cas dont tu parles? Ou en donner un?

    Car normalement les opérateurs '+' et '-', ont la même priorité.
    Je ne vois donc pas de raison pour lesquels ceci serait incorrect.
    A mon avis, s'il donne un exemple alors on trouvera de suite donc c'est pour ça qu'il n'en donne pas.

    C'est vrai que les opérateurs ont même priorité mais au niveau exécution, ils sont exécutés l'un après l'autre, avec cast implicite lors du calcul si les deux opérandes ne sont pas de même type. Et peut-être justement que a+b ne peut pas se faire cause cast impossible. Mais bon, c'est mon idée mais j'ai pas d'exemple qui s'y rapporte.

    En fait, cette idée est tirée de cet exemple
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    double res=3 / 2 * 10.0
    On pourrait croire que l'opération se passera dans le type le plus large des opérandes, (ici 10.0 de type double) donc on pourrait croire que le résultat sera comme 3.0 / 2.0 = 1.5 * 10.0 = 15.0

    Or, la première opération 3 / 2 se passant entre deux int, l'opération se fera en int => résultat 1. Puis, 1 multiplié par 10.0 donnera 10.0.

    Ptet que le a+b-c et a-c+b de Diogène c'est un peu le même principe...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #30
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    @Sve@r :
    A mon avis, s'il donne un exemple alors on trouvera de suite donc c'est pour ça qu'il n'en donne pas.
    Effectivement.

    Et peut-être justement que a+b ne peut pas se faire
    Effectivement.

    Un dernier indice :

    Dans certains cas, l'expression a+b-c est rejetée par le compilateur alors que a-c+b ou a+(b-c) sont acceptées.
    Pourquoi ?

  11. #31
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par diogene Voir le message
    Peut-on classer ceci comme une étrangeté ?

    Dans certains cas, l'expression a+b-c est rejetée par le compilateur alors que a-c+b esr acceptée.
    Pourquoi ?


    (Experts du langage, abstenez-vous de répondre, ce ne serait pas du jeu)
    C'est dans les cas comme ça que je regrette l'absence de balise [spoil]. Devoir écrire en blanc sur fond blanc ce n'est pas terrible.

    A priori, je dirais que "ce sont des pointeurs".

  12. #32
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    @gl :


  13. #33
    Membre averti
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 55
    Par défaut
    @gl
    Pourrait-on avoir un exemple s'il te plaît?

  14. #34
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 81
    Par défaut
    Si je ne dis pas de bêtises, l'arithmétique des pointeurs autorise :
    • l'addition/soustraction d'une valeur entière à un pointeur
    • la soustraction de deux pointeurs de même type (qui donne une valeur entière de type ptrdiff_t)

    L'addition de deux pointeurs n'est pas autorisé (et n'a pas beaucoup de sens finalement) ce qui fait que l'expression a+b-c ne peut être compilée (a+b étant évaluée en premier).

  15. #35
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 851
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 851
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ugo188 Voir le message
    Pourrait-on avoir un exemple s'il te plaît?
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int a[1];
    int *b=a;
    int *c=a;
     
    printf("%p\n", a - b + c);    // ok
    printf("%p\n", a + (c - b));  // ok
    printf("%p\n", a + c - b);    // Pb

    Accessoirement, je ne sais pas si on peut classer ça dans les bizarreries, mais ça me fait penser à ceci

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int *a=NULL;
    int *b=malloc(sizeof(int));
    int *c;
     
    printf("%p\n", a);    // ok, NULL est une valeur valide
    printf("%p\n", b);    // ok, malloc a renvoyé une valeur valide (une adresse allouée ou NULL)
    printf("%p\n", c);    // Comportement indéterminé - c ne contient pas de valeur valide (même s'il contient forcément quelque chose) et aller voir, donc ne serait-ce que sa valeur, est interdit
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  16. #36
    Membre averti
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 55
    Par défaut

    Citation:
    Envoyé par ugo188 Voir le message
    Pourrait-on avoir un exemple s'il te plaît?
    Code c :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    int a[1];
    int *b=a;
    int *c=a;
     
    printf("%p\n", a - b + c);    // ok
    printf("%p\n", a + (c - b));  // ok
    printf("%p\n", a + c - b);    // Pb
    Si je ne dis pas de bêtises, l'arithmétique des pointeurs autorise :

    * l'addition/soustraction d'une valeur entière à un pointeur
    * la soustraction de deux pointeurs de même type (qui donne une valeur entière de type ptrdiff_t)

    L'addition de deux pointeurs n'est pas autorisé (et n'a pas beaucoup de sens finalement) ce qui fait que l'expression a+b-c ne peut être compilée (a+b étant évaluée en premier).
    Merci pour cet exemple!
    Car en effet, ca prend tout son sens!

  17. #37
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 41
    Par défaut
    Citation Envoyé par diogene Voir le message
    Peut-on classer ceci comme une étrangeté ?

    Dans certains cas, l'expression a+b-c est rejetée par le compilateur alors que a-c+b esr acceptée.
    Pourquoi ?


    (Experts du langage, abstenez-vous de répondre, ce ne serait pas du jeu)
    Je pense que l'une des raisons est que, contrairement en mathématique, chez les ordinateurs l'addition, la soustraction (et les autres opérations arithmétiques d'ailleurs) ne sont pas des lois de compositions internes dans l'ensemble limité des entiers qu'ils (les ordis) peuvent manipuler. L'addition et la soustraction ne sont pas commutatives non plus.
    Les types de données (int, char, ...) ayant une taille fixe et donc un nombre maximal qu'il peuvent stocker, il se pourrait que dans a + b - c, (a + b) provoque inévitablement un dépassement de capacité détecté par le compilateur, qui jugera alors inutile de réaliser toute l'opération a + b - c (considérant que son résultat sera erroné). en revanche (a - c) peut être valide et son résultat additionné à b peut rester valide aussi. Le compilateur se taira.

    bref en mathématique, 255 + 1 - 1 = 255 - 1 + 1 (commutativité)
    mais en langage C (et en général avec les ordi) si vos types sont des unsigned char,
    255 + 1 - 1 != 255 - 1 + 1
    car 255 + 1 provoquera un dépassement....

  18. #38
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    (a + b) provoque inévitablement un dépassement de capacité détecté par le compilateur
    En général, le compilateur ne peut pas déterminer si il y a dépassement de capacité ou non. Celui-ci n'est évident qu'à l'exécution.
    en revanche (a - c) peut être valide
    Les possibilités de dépassement de capacité sont les mêmes que pour a+b

    mais en langage C (et en général avec les ordi) si vos types sont des unsigned char,
    255 + 1 - 1 != 255 - 1 + 1
    car 255 + 1 provoquera un dépassement....
    En C, si a, b et c sont unsigned char, ils seront automatiquement converti en int avant de faire l'opération (et le résultat sera un int). Il n'y aura pas de dépassement.

  19. #39
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 41
    Par défaut
    Merci pour toutes ces précisions, j'aurai quand même pu tester tout ce que j'ai débité avant d'écrire...

  20. #40
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 851
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 851
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Ulrik18 Voir le message
    Citation Envoyé par Ulrik18 Voir le message
    255 + 1 - 1 != 255 - 1 + 1
    car 255 + 1 provoquera un dépassement....
    Merci pour toutes ces précisions, j'aurai quand même pu tester tout ce que j'ai débité avant d'écrire...
    Et puis, même si on prend n le plus grand unsigned possible (2^32 dans la plupart des cas), alors n + 1 dépasse la taille maximale utilisée pour le calcul mais ce qui dépasse est tronqué et on ne garde que ce qui ne dépasse pas => dans ce cas 0.
    Et ensuite, 0 - 1 donnera (en hexa) 0xffffffff (si on reste dans l'exemple initial du long à 32 bits) mais comme on est en unsigned, cela sera retraduit en n
    Bref en fait, qu'il y ait dépassement ou pas, ici comme en maths, n + 1 - 1 = n - 1 + 1

    Citation Envoyé par Ulrik18 Voir le message
    L'addition et la soustraction ne sont pas commutatives non plus.
    La soustraction n'a jamais été commutative
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

Discussions similaires

  1. [langage] Je cherche un bon livre ?
    Par Anonymous dans le forum Langage
    Réponses: 13
    Dernier message: 09/04/2003, 13h16
  2. [langage] Comparer Perl avec d'autres langages comme C ?
    Par Anonymous dans le forum Langage
    Réponses: 3
    Dernier message: 10/08/2002, 23h52
  3. [langage] comment créer des fichiers ?
    Par Anonymous dans le forum Langage
    Réponses: 3
    Dernier message: 05/05/2002, 16h33
  4. Comparer des fichiers de données : Quel Langage ?
    Par Anonymous dans le forum Langages de programmation
    Réponses: 6
    Dernier message: 24/04/2002, 22h37
  5. Cours, tutoriels, logiciels, F.A.Q,... pour le langage SQL
    Par Marc Lussac dans le forum Langage SQL
    Réponses: 0
    Dernier message: 04/04/2002, 10h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo