Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there no gcc warning when a literal declared as long is assigned to an int in c?

I can compile and run a program that assigns a long int literal, albeit it one that would fit into an int, to an int variable.

$ 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: 1234

I know that 1234 would fit into an int but would still expect to be able to enable a warning. I've been through all the gcc options but can't find anything suitable.

Is it possible to generate a warning for this situation? From the discussion here, and the gcc options, the short answer is no. It isn't possible.

Would there be any point in such a warning? It's obvious in the trivial example I posted that 1234L is being assigned to an int variable, and that it will fit. However, what if the declaration and the assignment were separated by many lines of code? The programmer writing 1234L is signaling that they expect this literal integer to be assigned to a long. Otherwise, what's the point of appending the L?

In some situations, appending the L does make a difference. For example

$ cat sizeof-test.c 
#include <stdio.h>
void main(void){
  printf("%ld\n", sizeof(1234));
  printf("%ld\n", sizeof(1234L));
}
$ ./sizeof-test 
4
8

Although the compiler must know that 1234L would fit into a 4 byte int, it puts it into an 8 byte long.

$ 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)
like image 384
rgh Avatar asked Dec 01 '21 14:12

rgh


People also ask

Which option of GCC inhibit all warning messages?

If -Wfatal-errors is also specified, then -Wfatal-errors takes precedence over this option. Inhibit all warning messages. Make all warnings into errors.

How do I enable warnings in GCC?

GCC 4.3+ now has -Q --help=warnings , and you can even specify --help=warnings,C to just print out the C related warnings.

Which GCC flag is used to enable all compiler warnings?

gcc -Wall enables all compiler's warning messages. This option should always be used, in order to generate better code.

How do I ignore a warning in Makefile?

Maybe you can look for CFLAGS options in Makefile and remove the -Werror flag. The Werror flag will make all warnings into errors. Show activity on this post. In general, it is not a good idea to ignore warnings from your compiler.

How do I eliminate the warning-wparentheses in GCC for IF statements?

When there is the potential for this confusion, GCC issues a warning when this flag is specified. To eliminate the warning, add explicit braces around the innermost if statement so there is no way the else can belong to the enclosing if. The resulting code looks like this: This warning is enabled by -Wparentheses .

How to suppress the warning that X is always initialized in GCC?

If the value of y is always 1, 2 or 3, then x is always initialized, but GCC doesn’t know this. To suppress the warning, you need to provide a default case with assert(0) or similar code. This option also warns when a non-volatile automatic variable might be changed by a call to longjmp. The compiler sees only the calls to setjmp.

Why does GCC issue warnings when I use a common variable?

To help detect accidental misuses of such arrays GCC issues warnings unless it can prove that the use is safe. See Common Variable Attributes . Warn for cases where adding an attribute may be beneficial.

Why does GCC not keep track of variables state?

These warnings are only possible in optimizing compilation, because otherwise GCC does not keep track of the state of variables. These warnings are made optional because GCC may not be able to determine when the code is correct in spite of appearing to have an error. Here is one example of how this can happen:


2 Answers

Compilers should check the value range, not the type of the integer constant. Otherwise we would end up with a lot of whining whenever we initialize a small integer type, since there are no small integer constants smaller than int.

short i = 32768; does for example yield a warning with clang -Wconstant-conversion but not with gcc. There's -Wconversion but it's prone to false positives on either compiler.

If you want to guard against implicit conversions between various integer types, you should probably use a static analyser instead.

like image 112
Lundin Avatar answered Sep 29 '22 08:09

Lundin


In the case of constants, the compiler can see that the value in question fits into the type being assigned to, so there's really no point in warning. If the constant was out of range, i.e. 5000000000L, then the compiler will see that and generate a warning.

What the compiler can do however is warn when an integer type that is not a compile type constant is assigned to a lower type:

long y = 1;
int x = y;

If you add the -Wconversion flag (not included in either -Wall or -Wextra), you'll get this warning:

x1.c:6:5: warning: conversion to ‘int’ from ‘long int’ may alter its value [-Wconversion]
     int x = y;
like image 35
dbush Avatar answered Sep 29 '22 08:09

dbush