same code pelles c and gcc got different results.

Started by ander_cc, March 15, 2026, 11:30:22 AM

Previous topic - Next topic

ander_cc

#include <stdio.h>
#include <stdbit.h>
int main() {
    unsigned short a1 = 4;
unsigned int a2 = 4;

printf("a1 one:%u  a1 zero:%u\n", stdc_first_leading_one(a1), stdc_first_leading_zero(a1));
printf("a2 one:%u  a2 zero:%u\n", stdc_first_leading_one(a2), stdc_first_leading_zero(a2));
   
    return 0;
}
gcc 11.4 -std=c23
a1 one:14  a1 zero:1
a2 one:30  a2 zero:1
-----
pelles c 13.01
a1 one:3  a1 zero:16
a2 one:3  a2 zero:32
-----
WHY? and which is right?

rweidner

I didn't know the answer to this question. I asked ChatGPT.

QuoteChatGPT:

Assuming the usual widths on a typical modern desktop/compiler:

unsigned short = 16 bits

unsigned int = 32 bits

stdc_first_leading_one(x) returns the 1-based position of the first 1 when scanning from the most-significant bit (MSB).
stdc_first_leading_zero(x) returns the 1-based position of the first 0 when scanning from the MSB.

For 4, the bit pattern is ...00000100 (only bit 2 set, counting from LSB starting at 0):

First leading one is at position width - 2

First leading zero is at position 1 (because the MSB is 0 for the value 4)

So the output will be:

a1 one:14  a1 zero:1
a2 one:30  a2 zero:1

Explanation:

a1 (16-bit): 16 - 2 = 14

a2 (32-bit): 32 - 2 = 30

If you run this on a platform where unsigned int is not 32-bit (or unsigned short not 16-bit), the one: numbers will change accordingly, but the zero: values will still be 1 for 4 (since the MSB is still 0).

John Z

If (and a big if) I understand it, it appears the issue is the 'direction' of the counting

short int example

gcc and ChatGPT
a1 one:14  a1 zero:1
00000000 00000100 count left to right == 14 for 1st 1
00000000 00000100 count right to left ==  1 for 1st 0

Pelle version
a1 one:3  a1 zero:16
00000000 00000100 count right to left ==  3 for ist 1
00000000 00000100 count left to right == 16 for 1st 0

John Z

ander_cc


Pelle

This is from the C23 draft n3220.pdf (since I will never waste money on the real C23 standard; I don't know if the draft differs from the final version):

QuoteThe most significant index is the 0-based index counting from the most significant bit, 0, to the least significant bit, w − 1, where w is the width of the type that is having its most significant index computed.

The least significant index is the 0-based index counting from the least significant bit, 0, to the most significant bit, w − 1, where w is the width of the type that is having its least significant index computed.

QuoteFirst Leading Zero
Returns the most significant index of the first 0 bit in value, plus 1. If it is not found, this function returns 0.

QuoteFirst Leading One
Returns the most significant index of the first 1 bit in value, plus 1. If it is not found, this function returns 0.

What the <beep> <beep> <beep> are they actually saying here?! Can someone with better English skills than mine explain: from which direction is what counted...?
/Pelle

TimoVJL

gcc is multitarget compiler and see things in that way.
memory layout can be different in little-endian / big-endian things ?
May the source be with you

Pelle

Quote from: TimoVJL on March 27, 2026, 07:44:02 PMgcc is multitarget compiler and see things in that way.
memory layout can be different in little-endian / big-endian things ?
Yes, but these functions should operate on the loaded value, disregarding the memory byte-order.
I would like a second opinion to GCC, but few compilers seems to care about C23 in general, and <stdbit.h> especially...
/Pelle

John Z

Downloaded n3220 working draft.

Problem is not your English - it is the inconsistency in the proposed spec.

Sections 7.18.3 through 7.18.6 clearly indicate the direction to 'count' from. 'Leading' is from MSB to LSB,
'Trailing' is from LSB to MSB these are specifically spelled out in each of these sections under item #2.

However

Sections 7.18.7 through 7.18.12 drop the clarity. They seem to assume that everyone will guess "Leading" always means counting from MSB to LSB, and "Trailing" always means counting from LSB to MSB but do not ever specifically say so as in the previous sections.

Also have to be careful where some times use index as in Bit[0] - Bit[15] verses position Bit[1] - Bit[16]. or they say index +1 which is position or using w-1 which would be index  ::) different authors I'm guessing.

IMO -

John Z

Pelle

Quote from: John Z on Yesterday at 10:56:36 AMDownloaded n3220 working draft.

Problem is not your English - it is the inconsistency in the proposed spec.
Thanks for looking at this! Glad it's not just me, then...

Until there is a clearer picture, I will not change anything. The GCC distribution for Windows, that I have found in recent years (they seem to come and go), have been of somewhat dubious quality. I havn't seen this for LLVM yet. Microsoft may get to <stdbit.h> in 2035. Maybe.

For now, there are other functions doing the same job; for Windows: _BitScanForward(), _BitScanReverse(), _BitScanForward64(), and _BitScanReverse64(); more generic: _bit_scan_forward(), _bit_scan_forward64(), _bit_scan_reverse(), _bit_scan_reverse64(). No requirement on C23.
/Pelle