Pelles C forum

C language => Beginner questions => Topic started by: ander_cc on March 15, 2026, 11:30:22 AM

Title: same code pelles c and gcc got different results.
Post by: ander_cc on March 15, 2026, 11:30:22 AM
#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?
Title: Re: same code pelles c and gcc got different results.
Post by: rweidner on March 18, 2026, 02:11:00 PM
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).
Title: Re: same code pelles c and gcc got different results.
Post by: John Z on March 18, 2026, 03:44:17 PM
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
Title: Re: same code pelles c and gcc got different results.
Post by: ander_cc on March 19, 2026, 09:20:27 AM
Thank you, rweidner and John Z!
Title: Re: same code pelles c and gcc got different results.
Post by: Pelle on March 27, 2026, 07:16:45 PM
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...?
Title: Re: same code pelles c and gcc got different results.
Post by: TimoVJL on March 27, 2026, 07:44:02 PM
gcc is multitarget compiler and see things in that way.
memory layout can be different in little-endian / big-endian things ?
Title: Re: same code pelles c and gcc got different results.
Post by: Pelle on March 27, 2026, 07:58:36 PM
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...
Title: Re: same code pelles c and gcc got different results.
Post by: John Z on March 28, 2026, 10:56:36 AM
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
Title: Re: same code pelles c and gcc got different results.
Post by: Pelle on March 28, 2026, 12:34:09 PM
Quote from: John Z on March 28, 2026, 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.
Title: Re: same code pelles c and gcc got different results.
Post by: mid-kid on April 22, 2026, 09:50:18 PM
I've looked into the standard's explanation quoted above with a friend, and we came up with the following:

Quotestdc_first_leaning_one finds the first 1 bit, searching from most significant to least significant. The index of this bit is returned such that the most significant bit is 1 and the least significant bit is w, where w is the amount of bits in the data type. 0 is returned when no match was found.

The key to understanding the definition in the standard, is to realize that the term "most significant index" refers to a way of indexing the number and not a specific index.

I hope this helps solve the conundrum  :D
Title: Re: same code pelles c and gcc got different results.
Post by: Pelle on April 23, 2026, 10:21:31 AM
Quote from: mid-kid on April 22, 2026, 09:50:18 PMI hope this helps solve the conundrum  :D
Yes, it does. Thanks!  :)

This is the good news. The bad news is I have to go back and fix the code in several places. Bah.