Puedo compilar y ejecutar un programa que asigne un literal int largo, aunque sea uno que encaje en un int, a una variable int.
$ cat assign-long-to-int.c #include <stdio.h> int main(void){ int i = 1234L; //assign long to an int printf("i: %d\n", i); return 0; } $ gcc assign-long-to-int.c -o assign-long-to-int $ ./assign-long-to-int i: 1234Sé que 1234 encajaría en un int pero aún esperaría poder habilitar una advertencia. He revisado todas las opciones de gcc pero no puedo encontrar nada adecuado.
¿Es posible generar una advertencia para esta situación? De la discusión aquí, y las opciones de gcc, la respuesta corta es no. no es posible
¿Tendría algún sentido tal advertencia? Es obvio en el ejemplo trivial que publiqué que 1234L se asigna a una variable int y que encajará. Sin embargo, ¿qué pasaría si la declaración y la asignación estuvieran separadas por muchas líneas de código? El programador que escribe 1234L indica que espera que este entero literal se asigne a un largo. De lo contrario, ¿cuál es el punto de agregar la L?
En algunas situaciones, añadir la L marca la diferencia. Por ejemplo
$ cat sizeof-test.c #include <stdio.h> void main(void){ printf("%ld\n", sizeof(1234)); printf("%ld\n", sizeof(1234L)); } $ ./sizeof-test 4 8Aunque el compilador debe saber que 1234L cabría en un int de 4 bytes, lo coloca en un long de 8 bytes.
$ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none:hsa OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.3.0-17ubuntu1~20.04' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-HskZEa/gcc-9-9.3.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)Los compiladores deben verificar el rango de valores, no el tipo de la constante entera. De lo contrario, terminaríamos con muchas quejas cada vez que inicializamos un tipo de entero pequeño, ya que no hay constantes enteras pequeñas más pequeñas que int .
short i = 32768; por ejemplo, produce una advertencia con clang -Wconstant-conversion pero no con gcc. Hay -Wconversion pero es propenso a falsos positivos en cualquiera de los compiladores.
Si desea protegerse contra las conversiones implícitas entre varios tipos de enteros, probablemente debería usar un analizador estático en su lugar.
En el caso de las constantes, el compilador puede ver que el valor en cuestión se ajusta al tipo que se le asigna, por lo que no tiene sentido advertir. Si la constante estaba fuera de rango, es decir, 5000000000L , el compilador lo verá y generará una advertencia.
Sin embargo, lo que el compilador puede hacer es advertir cuando un tipo entero que no es una constante de tipo de compilación se asigna a un tipo inferior:
long y = 1; int x = y; Si agrega el indicador -Wconversion (no incluido en -Wall o -Wextra ), recibirá esta advertencia:
x1.c:6:5: warning: conversion to 'int' from 'long int' may alter its value [-Wconversion] int x = y;El compilador convertirá automáticamente entre la mayoría de los tipos de enteros primitivos. Cuando convierte de un tipo más grande a un tipo más pequeño, estoy bastante seguro de que es una característica del lenguaje C que el número se truncará.
Por ejemplo, el siguiente código imprimirá "0xef":
#include <stdio.h> #include <stdint.h> int main() { uint32_t x = 0xdeadbeef; uint8_t y = x; printf("0x%x\n", y); return 0; }Para abordar su pregunta específicamente, no creo que haya una advertencia para este comportamiento, porque esta conversión es técnicamente una característica definida del lenguaje C.