public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* signed/unsigned integer conversion for right shift seems against C99 rule
@ 2018-02-06 15:03 Peter Breuer
  2018-02-06 15:21 ` Tadeus Prastowo
                   ` (2 more replies)
  0 siblings, 3 replies; 39+ messages in thread
From: Peter Breuer @ 2018-02-06 15:03 UTC (permalink / raw)
  To: gcc-help

int main() {
  signed   int x = 0x80000005u;
  unsigned int y = 0x00000002u;
  signed   int z = x >> y;
  printf("0x%0x\n", z);
  return 0;
}
% gcc -std=c99 test.c 
test.c: In function 'main':
test.c:6:3: warning: implicit declaration of function 'printf' [-Wimplicit-function-declaration]
   printf("0x%0x\n", z);
   ^
test.c:6:3: warning: incompatible implicit declaration of built-in function 'printf'

(I'll live with that warning - just for the purpose of a clean example!)

% ./a.out
0xe0000001
  ^ SIGNED right shift

OK, so x>>y was done signed. That means both x,y were converted to
signed int (trivially).

However, that seems against C99 rules, which seem to say one should
convert to unsigned int in mixed sign equal rank situations.

First: NO INTEGER PROMOTION is done, by this rule

  any operand whose type ranks lower than int is automatically converted
  to the type int, provided int is capable of representing all values of
  the operand's original type.  If int is not sufficient, the operand is
  converted to unsigned int.

Both x and y are int, so do not rank "lower than int". Rule does not
apply. All as is. So INTEGER CONVERSION applies from there:

  If both operands are integers, integer promotion is first performed on
  both operands.  If after integer promotion the operands still have
  different types, conversion continues as follows:

They still have "different types", one being signed int and the other
being unsigned it. So CONVERSION happens:

  If one operand has an unsigned type T whose conversion rank is at
  least as high as that of the other operand's type, then the other
  operand is converted to type T.

We're there. Both are rank "int" so "at least as high" applies. One
(y) has an unsigned type T="unsigned int", so the other (x) must
be converted to T="unsigned int". Then the operation gets done as
  
 unsigned int >> unsigned int

Except it doesn't. The sign bit on the LHS was extended as the printf
showed with its "0xe..." at the front, so a shift-right-arithmetic got
done, not a shift-right-logical.

If you wonder if a SRL is available at all, it is.  Declaring both x and
y as unsigned int (i.e., change decl of x only to unsigned int) gives
the expected SRL output.

  % ./a.out
  0x20000001
    ^ zero-extended from 0x8..., not sign-extended. That's a SRL, not a SRA.

What am I reading wrong in the standards?  (which are nigh on
incomprehensible - what does "can be represented as" mean?  One can't
represent negative numbers in the unsigned version of the same type
ever, and one can't represent large positive numbers in the signed
version of the type ever, so one can never get "can be represented as").

Is this intended? Well-known to everyone but me?


% gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i586-linux-gnu/4.9/lto-wrapper
Target: i586-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.9.2-10'
 --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs
 --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
 --program-suffix=-4.9 --enable-shared --enable-linker-build-id
 --libexecdir=/usr/lib --without-included-gettext
 --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9
 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu
 --enable-libstdcxx-debug --enable-libstdcxx-time=yes
 --enable-gnu-unique-object --disable-vtable-verify --enable-plugin
 --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk
 --enable-gtk-cairo
 --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.9-i386/jre
 --enable-java-home
 --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.9-i386
 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.9-i386
 --with-arch-directory=i386
 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc
 --enable-targets=all --enable-multiarch --with-arch-32=i586
 --with-multilib-list=m32,m64,mx32 --enable-multilib
 --with-tune=generic --enable-checking=release --build=i586-linux-gnu
 --host=i586-linux-gnu --target=i586-linux-gnu Thread model: posix gcc
 version 4.9.2 (Debian 4.9.2-10) 

The gcc notes at https://gcc.gnu.org/c99status.html seem to say 

  integer constant type rules   GCC 3.3 
  integer promotion rules GCC 4.0 

and nothing else.  Where is current information on standards compliance?
The manual  says

  c99
           c9x
           iso9899:1999
           iso9899:199x
           ISO C99.  Note that this standard is not yet fully supported;
                                               ^^^^^^^^^^^^^^^^^^^^^^^^
           see <http://gcc.gnu.org/gcc-4.7/c99status.html> for more
           information.  The names c9x and iso9899:199x are deprecated.



Any info that would deconfuse me?

Regards to any language lawyers who pass by on the other side or this side.

PTB

^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2018-02-07 18:50 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-06 15:03 signed/unsigned integer conversion for right shift seems against C99 rule Peter Breuer
2018-02-06 15:21 ` Tadeus Prastowo
2018-02-06 15:29   ` signed/unsigned integer conversion for right shift seems against Peter T. Breuer
2018-02-06 15:38     ` Tadeus Prastowo
2018-02-06 16:17       ` Peter T. Breuer
2018-02-06 15:22 ` signed/unsigned integer conversion for right shift seems against C99 rule Alexander Monakov
2018-02-06 15:22 ` Liu Hao
2018-02-06 15:31   ` David Brown
2018-02-06 15:50   ` signed/unsigned integer conversion for right shift seems Peter T. Breuer
2018-02-06 15:57     ` Jonathan Wakely
2018-02-06 16:42       ` Peter T. Breuer
2018-02-06 16:45         ` Jonathan Wakely
2018-02-06 17:19           ` Peter T. Breuer
2018-02-06 17:35             ` Jonathan Wakely
2018-02-06 18:23               ` Peter T. Breuer
2018-02-06 18:27                 ` Jonathan Wakely
2018-02-06 18:37                   ` Tadeus Prastowo
2018-02-06 18:47                     ` Jonathan Wakely
2018-02-06 19:43                       ` Peter T. Breuer
2018-02-06 20:08                         ` Tadeus Prastowo
2018-02-06 20:15                           ` Jonathan Wakely
2018-02-07  9:59                             ` Peter T. Breuer
2018-02-07 12:28                               ` David Brown
     [not found]                                 ` <201802071634.w17GYiEL000904@nbd.it.uc3m.es>
2018-02-07 16:39                                   ` Jonathan Wakely
2018-02-07 17:25                                     ` Peter T. Breuer
2018-02-07 17:39                                       ` Tadeus Prastowo
2018-02-07 18:50                                         ` Peter T. Breuer
2018-02-07 17:39                                       ` Jonathan Wakely
2018-02-07 18:32                                         ` Peter T. Breuer
2018-02-07 18:41                                           ` Jonathan Wakely
2018-02-07 18:11                                       ` Jonathan Wakely
2018-02-06 19:28                   ` Peter T. Breuer
2018-02-06 20:11                     ` Jonathan Wakely
2018-02-06 23:49                       ` Peter T. Breuer
2018-02-07  2:04                         ` Vincent Lefevre
2018-02-07  9:30                           ` Peter T. Breuer
2018-02-06 21:18                 ` Chris Hall
2018-02-06 17:44             ` Tadeus Prastowo
2018-02-06 19:00               ` Peter T. Breuer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).