web-dev-qa-db-fra.com

Pourquoi la mention "2i;" PAS provoquer une erreur de compilation?

Au lieu de 2*i, J'ai écrit négligemment 2i:

int foo(int i)
{
    2i;
    return 2i;
}

Je m'attendais à ce que le compilateur détecte l'erreur. Mais ce ne fut pas le cas. 2i Est-il donc une déclaration valide en C? Si oui, que fait-il? Perplexe!

J'ai compilé en utilisant gcc version 5.3.0 et voici la sortie de l'assembly:

    .file   "strange.c"
    .text
    .globl  foo
    .type   foo, @function
foo:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    %edi, -4(%rbp)
    nop
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   foo, .-foo
    .ident  "GCC: (GNU) 5.3.0"
    .section    .note.GNU-stack,"",@progbits
82
daltonfury42

Il s'agit d'une extension gcc et 2i est la constante imaginaire enter image description here . Vous pouvez donc écrire un nombre complexe comme ceci:

#include <complex.h>

_Complex x = 4 + 5i;
106
Iharob Al Asimi

2i est une extension gcc pour un littéral entier complexe, un nombre imaginaire pur deux fois la racine carrée de -1. Cette extension est également prise en charge par clang.

Il est quelque peu surprenant que votre compilation avec gcc 5.4.0 produit la sortie Assembly publiée:

  • Compilation sur http://gcc.godbolt.org/# J'obtiens une erreur de compilation de gcc 5.3.0: http://gcc.godbolt.org/#: error: cannot convert '__complex__ int' to 'int' in return.
  • Le code d'assembly publié pour la fonction foo est incorrect: il ne renvoie pas 0. Conversion de la constante entière complexe 2i à int devrait retourner sa partie réelle 0.

Inversement, avec clang 3.7, il compile sans avertissement et génère du code optimal, mais bien sûr pas ce que vous attendez:

foo(int):                       # @foo(int)
    xorl    %eax, %eax
    retq

Cette syntaxe peut être combinée avec d'autres suffixes dans n'importe quel ordre. Compilation du code ci-dessous avec clang -Weverything me donne des avertissements appropriés warning: imaginary constants are a GNU extension [-Wgnu-imaginary-constant]:

#include <stdio.h>

int main() {
    /* complex integer literals */
    printf("sizeof(2i) = %zd\n", sizeof(2i));
    printf("sizeof(2ui) = %zd\n", sizeof(2ui));
    printf("sizeof(2li) = %zd\n", sizeof(2li));
    printf("sizeof(2lli) = %zd\n", sizeof(2lli));
    /* complex floating point literals */
    printf("sizeof(2.i) = %zd\n", sizeof(2.i));
    printf("sizeof(2.fi) = %zd\n", sizeof(2.fi));
    printf("sizeof(2e0fi) = %zd\n", sizeof(2e0fi));
    printf("sizeof(2e0i) = %zd\n", sizeof(2e0i));
    /* alternate order */
    printf("sizeof(2il) = %zd\n", sizeof(2il));
    printf("sizeof(2ill) = %zd\n", sizeof(2ill));
    printf("sizeof(2.if) = %zd\n", sizeof(2.if));

    return 0;
}

Il produit cette sortie dans mon environnement:

sizeof(2i) = 8
sizeof(2ui) = 8
sizeof(2li) = 16
sizeof(2lli) = 16
sizeof(2.i) = 16
sizeof(2.fi) = 8
sizeof(2e0fi) = 8
sizeof(2e0i) = 16
sizeof(2il) = 16
sizeof(2ill) = 16
sizeof(2.if) = 8

Essayez le dernier avec votre éditeur de coloration syntaxique ;-)

13
chqrlie