Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-

Least favorite C style

Name: Anonymous 2016-10-01 6:42

http://stackoverflow.com/questions/11187150/gcc-weird-integer-promotion-scheme
Did you know C standard silently promotes integers to larger size, because "its good for you". Portable assembler my ass.

Name: Anonymous 2016-10-01 7:07

Yeah, C is shit. Datasizes should be completely abstracted away unless explicitly specified. Let the compile figure out how it works.

Name: Anonymous 2016-10-01 13:54

The reason C behaves this way is to allow for platforms where ALU operations on sub-int types are less efficient than those on full int types.

Name: Cudder !cXCudderUE 2016-10-01 14:37

>>1
This isn't gcc, this is standard C semantics.
As usual on SO, the "accepted" answer completely misses the mark. The standard is worded that way so things like short x = 32767, y = 5000; int z = x + y will naturally work. It doesn't mean the implementation has to actually do any widening if it doesn't make any observable difference.

Any sane compiler would realise that the promotion is useless in the case of addition and subtraction with shorts because the arithmetic turns out the same either way. Adding an int to a short and then assigning to a short should cause a warning, because there is the possibility of truncation.

Of course, GCC is not a sane compiler.

Name: Anonymous 2016-10-01 16:41

Did you know C standard silently promotes integers to larger size, because "its good for you".
Yes, I did.
The rule is actually simple: C can only do integral arithmetic on int and long (if required) types, and not on short or char.
The Standard implies a load-store machine, where any integral data gets loaded into either an int- or long-sized register (sign or zero extending if necessary), then the calculation is done and then the result gets written back to memory (truncating it if necessary).
RAM (usually 8, 16, 32 or 64 bit words) -> CPU (usually 32 or 64 bit words nowadays) -> RAM again (...)
'So, whats the point with chars and shorts, anyway?', you may ask. To save memory space, basically. Char (array) is usually used for storing strings and short for storing numbers in the up to 10000 or so range (e.g. list of indices for a small-ish array).
The same *should* go for floats and doubles, too, but is not required by the standard: floats for storing, doubles for calculations.

Name: Cudder !cXCudderUE 2016-10-01 16:55

>>5
Introduce a double into a calculation involving shorts and ints, and the final result will also be a double.

The standard leaves a lot unspecified, but if you add two chars together and store the result in a char, a compiler should be smart enough to figure out that no widening is needed because it doesn't matter one bloody bit.

Name: Anonymous 2016-10-01 17:40

>>6
The Ada SPARK compiler is smart enough to suggest a a/2 + b/2 in place of (a + b)/2 because the former is safer overflow-wise.
The GCC isn't smart enough to understand that adding two shorts should result in a short.

Name: Anonymous 2016-10-01 18:17

>>6
GCC seems to emit correctly sized ops only for unsigned operands and long/long long ops for signed. Maybe we're forgetting something?
Here's my test file (compile with 'gcc -S'):
#include <stdint.h>
#define CATN(t) F ## t
#define FN(T) T CATN(T)(T u, T v) {return u / v;}

FN(uint8_t)
FN(int8_t)
FN(uint16_t)
FN(int16_t)
FN(unsigned)
FN(int)
FN(uint32_t)
FN(int32_t)
FN(uint64_t)
FN(int64_t)

Name: Anonymous 2016-10-02 5:26

-S -Ofast -fno-exceptions
.file "test.c"
.text
.p2align 4,,15
.globl Fuint8_t
.def Fuint8_t; .scl 2; .type 32; .endef
.seh_proc Fuint8_t
Fuint8_t:
.seh_endprologue
movzbl %cl, %eax
divb %dl
ret
.seh_endproc
.p2align 4,,15
.globl Fint8_t
.def Fint8_t; .scl 2; .type 32; .endef
.seh_proc Fint8_t
Fint8_t:
.seh_endprologue
movsbl %cl, %eax
movsbl %dl, %r8d
cltd
idivl %r8d
ret
.seh_endproc
.p2align 4,,15
.globl Fuint16_t
.def Fuint16_t; .scl 2; .type 32; .endef
.seh_proc Fuint16_t
Fuint16_t:
.seh_endprologue
movl %edx, %r8d
movl %ecx, %eax
xorl %edx, %edx
divw %r8w
ret
.seh_endproc
.p2align 4,,15
.globl Fint16_t
.def Fint16_t; .scl 2; .type 32; .endef
.seh_proc Fint16_t
Fint16_t:
.seh_endprologue
movswl %cx, %eax
movswl %dx, %r8d
cltd
idivl %r8d
ret
.seh_endproc
.p2align 4,,15
.globl Funsigned
.def Funsigned; .scl 2; .type 32; .endef
.seh_proc Funsigned
Funsigned:
.seh_endprologue
movl %edx, %r8d
movl %ecx, %eax
xorl %edx, %edx
divl %r8d
ret
.seh_endproc
.p2align 4,,15
.globl Fint
.def Fint; .scl 2; .type 32; .endef
.seh_proc Fint
Fint:
.seh_endprologue
movl %ecx, %eax
movl %edx, %r8d
cltd
idivl %r8d
ret
.seh_endproc
.p2align 4,,15
.globl Fuint32_t
.def Fuint32_t; .scl 2; .type 32; .endef
.seh_proc Fuint32_t
Fuint32_t:
.seh_endprologue
movl %edx, %r8d
movl %ecx, %eax
xorl %edx, %edx
divl %r8d
ret
.seh_endproc
.p2align 4,,15
.globl Fint32_t
.def Fint32_t; .scl 2; .type 32; .endef
.seh_proc Fint32_t
Fint32_t:
.seh_endprologue
movl %ecx, %eax
movl %edx, %r8d
cltd
idivl %r8d
ret
.seh_endproc
.p2align 4,,15
.globl Fuint64_t
.def Fuint64_t; .scl 2; .type 32; .endef
.seh_proc Fuint64_t
Fuint64_t:
.seh_endprologue
movq %rdx, %r8
movq %rcx, %rax
xorl %edx, %edx
divq %r8
ret
.seh_endproc
.p2align 4,,15
.globl Fint64_t
.def Fint64_t; .scl 2; .type 32; .endef
.seh_proc Fint64_t
Fint64_t:
.seh_endprologue
movq %rcx, %rax
movq %rdx, %r8
cqto
idivq %r8
ret
.seh_endproc
.ident "GCC: (GNU) 6.1.0"

Name: Anonymous 2016-10-02 5:44

gcc.exe -S -Ofast -fno-except
ions -fno-asynchronous-unwind-tables
.file "test.c"
.text
.p2align 4,,15
.globl Fuint8_t
.def Fuint8_t; .scl 2; .type 32; .endef
Fuint8_t:
movzbl %cl, %eax
divb %dl
ret
.p2align 4,,15
.globl Fint8_t
.def Fint8_t; .scl 2; .type 32; .endef
Fint8_t:
movsbl %cl, %eax
movsbl %dl, %r8d
cltd
idivl %r8d
ret
.p2align 4,,15
.globl Fuint16_t
.def Fuint16_t; .scl 2; .type 32; .endef
Fuint16_t:
movl %edx, %r8d
movl %ecx, %eax
xorl %edx, %edx
divw %r8w
ret
.p2align 4,,15
.globl Fint16_t
.def Fint16_t; .scl 2; .type 32; .endef
Fint16_t:
movswl %cx, %eax
movswl %dx, %r8d
cltd
idivl %r8d
ret
.p2align 4,,15
.globl Funsigned
.def Funsigned; .scl 2; .type 32; .endef
Funsigned:
movl %edx, %r8d
movl %ecx, %eax
xorl %edx, %edx
divl %r8d
ret
.p2align 4,,15
.globl Fint
.def Fint; .scl 2; .type 32; .endef
Fint:
movl %ecx, %eax
movl %edx, %r8d
cltd
idivl %r8d
ret
.p2align 4,,15
.globl Fuint32_t
.def Fuint32_t; .scl 2; .type 32; .endef
Fuint32_t:
movl %edx, %r8d
movl %ecx, %eax
xorl %edx, %edx
divl %r8d
ret
.p2align 4,,15
.globl Fint32_t
.def Fint32_t; .scl 2; .type 32; .endef
Fint32_t:
movl %ecx, %eax
movl %edx, %r8d
cltd
idivl %r8d
ret
.p2align 4,,15
.globl Fuint64_t
.def Fuint64_t; .scl 2; .type 32; .endef
Fuint64_t:
movq %rdx, %r8
movq %rcx, %rax
xorl %edx, %edx
divq %r8
ret
.p2align 4,,15
.globl Fint64_t
.def Fint64_t; .scl 2; .type 32; .endef
Fint64_t:
movq %rcx, %rax
movq %rdx, %r8
cqto
idivq %r8
ret
.ident "GCC: (GNU) 6.1.0"

Name: Anonymous 2016-10-02 16:07

>>10
Checkem!!!1!!

Name: Anonymous 2016-10-02 16:45

warning: implicit conversion increases floating-point precision: 'float' to 'double' [-Wdouble-promotion]

Don't change these.
Name: Email:
Entire Thread Thread List