En lugar de 2*i
, escribí descuidadamente 2i
:
int foo(int i)
{
2i;
return 2i;
}
Esperaba que el compilador detectara el error. Pero no lo hizo. Entonces, ¿es 2i
una declaración válida en C? Si es así, ¿qué hace? ¡Perplejo!
Compilé usando gcc versión 5.3.0 y aquí está el resultado del ensamblaje:
.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
_Complex
números. Después de leer un poco el estándar y el enlace proporcionado, creo que la respuesta de @ iharob es correcta._Complex
tipo. Descubrí esto mientras escribía un software de procesamiento de datos para mi tesis ( Física en realidad, no informática ni nada parecido ) ( tuve que aplicar un filtro de paso bajo, por lo que la convolución es la Transformada rápida de Fourier, así que sigues adelante ).Respuestas:
Esta es una extensión gcc y
2i
es la constante imaginaria . Entonces puedes escribir un número complejo así:#include <complex.h> _Complex x = 4 + 5i;
fuente
_Complex
tipo,2i
es una constante ( como lo entiende gcc ). Agregue la banderastd=c99
ostd=c11
combinada con-Wall
y verá una advertencia. Además, de hecho no devuelve,0
pero dado que el tipo de retorno debe ser_Complex
y el valor0 + 2i
, no puede inspeccionarlo conprintf()
. ¡Quizás esa sea solo la parte real0
!#include <float.h>
(omath.h
) obtener soporte para constantes de punto flotante .#pragma
, lo quecomplex.h
podría generar un problema. Pero no lo hicieron de esta manera.2i
es unagcc
extensión de un literal entero complejo, un número imaginario puro dos veces la raíz cuadrada de-1
. Esta extensión también es compatible conclang
.Es algo sorprendente que su compilación
gcc 5.4.0
produzca el resultado del ensamblado publicado:gcc
5.3.0http://gcc.godbolt.org/#
::error: cannot convert '__complex__ int' to 'int' in return
.foo
es incorrecto: no regresa0
. La conversión de la constante entera compleja2i
enint
debería devolver su parte real0
.Por el contrario, con
clang
3.7, se compila sin una advertencia y genera un código óptimo, pero por supuesto no es lo que esperas:foo(int): # @foo(int) xorl %eax, %eax retq
Esta sintaxis se puede combinar con otros sufijos en cualquier orden. Compilar el código a continuación con
clang -Weverything
me da las advertencias adecuadaswarning: 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; }
Produce esta salida en mi entorno:
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
Prueba el último con tu editor de colores de sintaxis
;-)
fuente