• Why is this happening?

    From DFS@3:633/10 to All on Fri Mar 27 00:12:55 2026

    I time various operations, and the valid results are normally like:

    1 operation 1 0.019s
    2 operation 2 0.064s
    3 operation 3 0.000s
    4 operation 4 0.004s
    5 operation 5 0.001s
    6 operation 6 0.089s


    But every 10th to 15th run, the results are FUBAR:

    1 operation 1 0.019s
    2 operation 2 -0.936s
    3 operation 3 0.000s
    4 operation 4 0.004s
    5 operation 5 0.002s
    6 operation 6 -0.911s


    -----------------------------------------------------------------------
    timing structure and functions -----------------------------------------------------------------------
    struct timespec master, start, stop;

    void beginmastertimer() {clock_gettime(CLOCK_MONOTONIC_RAW, &master);}

    void begintimer() {clock_gettime(CLOCK_MONOTONIC_RAW, &start);}

    double elapsed(struct timespec started) {
    const double B = 1e9;
    clock_gettime(CLOCK_MONOTONIC_RAW,&stop);
    return ((stop.tv_sec-started.tv_sec) + (stop.tv_nsec-started.tv_nsec)) / B;
    }



    -----------------------------------------------------------------------
    timing of operations -----------------------------------------------------------------------
    const char *ops[] = {"operation 1", "operation 2", "operation 3",
    "operation 4", "operation 5", "operation 6"};

    double results[6] = {0.0};

    beginmastertimer(); //begin overall timing

    begintimer();
    operation1();
    results[0] = elapsed(start);

    begintimer();
    operation2();
    results[1] = elapsed(start);

    ...

    results[5] = elapsed(master); //end of overall timing

    The output is:
    printf("%d %-15s %.3fs\n", i+1, ops[i], results[i]);



    Anything stand out?

    Thanks

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Janis Papanagnou@3:633/10 to All on Fri Mar 27 05:46:55 2026
    Subject: Why is this happening?

    I think because you are doing wrong calculations here:

    return ((stop.tv_sec-started.tv_sec) +
    (stop.tv_nsec-started.tv_nsec)) / B;

    You should not subtract the components s/ns separately when scaling.
    Instead build the float stop number and started number separately and
    then subtract.

    Janis


    On 2026-03-27 05:12, DFS wrote:

    I time various operations, and the valid results are normally like:

    1˙ operation 1˙˙˙˙ 0.019s
    2˙ operation 2˙˙˙˙ 0.064s
    3˙ operation 3˙˙˙˙ 0.000s
    4˙ operation 4˙˙˙˙ 0.004s
    5˙ operation 5˙˙˙˙ 0.001s
    6˙ operation 6˙˙˙˙ 0.089s


    But every 10th to 15th run, the results are FUBAR:

    1˙ operation 1˙˙˙˙ 0.019s
    2˙ operation 2˙˙˙˙ -0.936s
    3˙ operation 3˙˙˙˙ 0.000s
    4˙ operation 4˙˙˙˙ 0.004s
    5˙ operation 5˙˙˙˙ 0.002s
    6˙ operation 6˙˙˙˙ -0.911s


    ----------------------------------------------------------------------- timing structure and functions ----------------------------------------------------------------------- struct timespec master, start, stop;

    void beginmastertimer() {clock_gettime(CLOCK_MONOTONIC_RAW, &master);}

    void begintimer()˙˙˙˙˙˙ {clock_gettime(CLOCK_MONOTONIC_RAW, &start);}

    double elapsed(struct timespec started) {
    ˙˙˙˙const double B = 1e9;
    ˙˙˙˙clock_gettime(CLOCK_MONOTONIC_RAW,&stop);
    ˙˙˙˙return ((stop.tv_sec-started.tv_sec) + (stop.tv_nsec-
    started.tv_nsec)) / B;
    }



    ----------------------------------------------------------------------- timing of operations -----------------------------------------------------------------------
    const char *ops[] = {"operation 1", "operation 2", "operation 3",
    "operation 4", "operation 5", "operation 6"};

    double results[6] = {0.0};

    beginmastertimer();˙ //begin overall timing

    begintimer();
    operation1();
    results[0] = elapsed(start);

    begintimer();
    operation2();
    results[1] = elapsed(start);

    ...

    results[5] = elapsed(master);˙ //end of overall timing

    The output is:
    printf("%d˙ %-15s˙ %.3fs\n", i+1, ops[i], results[i]);



    Anything stand out?

    Thanks


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Janis Papanagnou@3:633/10 to All on Fri Mar 27 06:01:57 2026
    On 2026-03-27 05:46, Janis Papanagnou wrote:
    Subject: Why is this happening?

    I think because you are doing wrong calculations here:

    return ((stop.tv_sec-started.tv_sec) + (stop.tv_nsec-
    started.tv_nsec)) / B;

    I have to correct myself; it should be sufficient if you apply the
    scaling factor correctly just to the ns component (not to the whole expression).


    You should not subtract the components s/ns separately when scaling.
    Instead build the float stop number and started number separately and
    then subtract.

    Janis


    On 2026-03-27 05:12, DFS wrote:

    I time various operations, and the valid results are normally like:

    1˙ operation 1˙˙˙˙ 0.019s
    2˙ operation 2˙˙˙˙ 0.064s
    3˙ operation 3˙˙˙˙ 0.000s
    4˙ operation 4˙˙˙˙ 0.004s
    5˙ operation 5˙˙˙˙ 0.001s
    6˙ operation 6˙˙˙˙ 0.089s


    But every 10th to 15th run, the results are FUBAR:

    1˙ operation 1˙˙˙˙ 0.019s
    2˙ operation 2˙˙˙˙ -0.936s
    3˙ operation 3˙˙˙˙ 0.000s
    4˙ operation 4˙˙˙˙ 0.004s
    5˙ operation 5˙˙˙˙ 0.002s
    6˙ operation 6˙˙˙˙ -0.911s


    -----------------------------------------------------------------------
    timing structure and functions
    -----------------------------------------------------------------------
    struct timespec master, start, stop;

    void beginmastertimer() {clock_gettime(CLOCK_MONOTONIC_RAW, &master);}

    void begintimer()˙˙˙˙˙˙ {clock_gettime(CLOCK_MONOTONIC_RAW, &start);}

    double elapsed(struct timespec started) {
    ˙˙˙˙˙const double B = 1e9;
    ˙˙˙˙˙clock_gettime(CLOCK_MONOTONIC_RAW,&stop);
    ˙˙˙˙˙return ((stop.tv_sec-started.tv_sec) + (stop.tv_nsec-
    started.tv_nsec)) / B;
    }



    -----------------------------------------------------------------------
    timing of operations
    -----------------------------------------------------------------------
    const char *ops[] = {"operation 1", "operation 2", "operation 3",
    "operation 4", "operation 5", "operation 6"};

    double results[6] = {0.0};

    beginmastertimer();˙ //begin overall timing

    begintimer();
    operation1();
    results[0] = elapsed(start);

    begintimer();
    operation2();
    results[1] = elapsed(start);

    ...

    results[5] = elapsed(master);˙ //end of overall timing

    The output is:
    printf("%d˙ %-15s˙ %.3fs\n", i+1, ops[i], results[i]);



    Anything stand out?

    Thanks



    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From DFS@3:633/10 to All on Fri Mar 27 02:31:17 2026
    On 3/27/2026 1:01 AM, Janis Papanagnou wrote:
    On 2026-03-27 05:46, Janis Papanagnou wrote:
    Subject: Why is this happening?

    I think because you are doing wrong calculations here:

    return ((stop.tv_sec-started.tv_sec) + (stop.tv_nsec-
    started.tv_nsec)) / B;

    I have to correct myself; it should be sufficient if you apply the
    scaling factor correctly just to the ns component (not to the whole expression).

    Yes.

    What happened is I earlier today changed the parentheses from the
    original I used for years:

    (stopped.tv_sec-started.tv_sec) + (stopped.tv_nsec-started.tv_nsec) / B;

    to the incorrect:

    ((stopped.tv_sec-started.tv_sec) + (stopped.tv_nsec-started.tv_nsec)) / B;


    For clarity I now use:
    (stopped.tv_sec-started.tv_sec) + ((stopped.tv_nsec-started.tv_nsec) / B);


    Thanks for looking at it.



    You should not subtract the components s/ns separately when scaling.
    Instead build the float stop number and started number separately and
    then subtract.

    Janis


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Josef MĂśllers@3:633/10 to All on Fri Mar 27 10:15:23 2026
    On 27.03.26 05:46, Janis Papanagnou wrote:
    Subject: Why is this happening?

    I think because you are doing wrong calculations here:

    return ((stop.tv_sec-started.tv_sec) + (stop.tv_nsec-
    started.tv_nsec)) / B;

    You should not subtract the components s/ns separately when scaling.
    Instead build the float stop number and started number separately and
    then subtract.

    I usually subtract the nsec parts and if the result is negative, adjust
    the sec and the nsec parts accordingly:

    diffs = stop.tv_sec-started.tv_sec;
    if ((diffns = stop.tv_nsec- started.tv_nsec) < 0)
    {
    diffs --;
    diffns += 1000000000UL;
    }

    Josef

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Scott Lurndal@3:633/10 to All on Fri Mar 27 16:02:47 2026
    =?UTF-8?Q?Josef_M=C3=B6llers?= <josef@invalid.invalid> writes:
    On 27.03.26 05:46, Janis Papanagnou wrote:
    Subject: Why is this happening?

    I think because you are doing wrong calculations here:

    return ((stop.tv_sec-started.tv_sec) + (stop.tv_nsec-
    started.tv_nsec)) / B;

    You should not subtract the components s/ns separately when scaling.
    Instead build the float stop number and started number separately and
    then subtract.

    I usually subtract the nsec parts and if the result is negative, adjust
    the sec and the nsec parts accordingly:

    I don't use floating point when unsigned integers are most
    appropriate (which describes the actually implementation of
    tv_sec/tv_nsec on pretty much every single implementation
    in existence). For printing, just scale the unsigned
    integer appropriately.

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lawrence D?Oliveiro@3:633/10 to All on Sat Mar 28 01:46:56 2026
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M”llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Fri Mar 27 20:41:46 2026
    Lawrence D?Oliveiro <ldo@nz.invalid> writes:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M”llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator, copied
    from C++:

    diffns += 1'000'000'000UL;

    (I would have preferred underscores, but that would have conflicted
    with C++'s user-defined literals.)

    And of course any pre-C23 C compiler or any C compiler invoked in
    pre-C23 mode, will not recognize digit separators (unless it supports
    them as an extension).

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Janis Papanagnou@3:633/10 to All on Sat Mar 28 05:17:27 2026
    On 2026-03-28 04:41, Keith Thompson wrote:
    Lawrence D?Oliveiro <ldo@nz.invalid> writes:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M”llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator, copied
    from C++:

    diffns += 1'000'000'000UL;

    I think that's fine, much better than parsing those huge numbers.
    (A convention used in Switzerland, IIRC.)


    (I would have preferred underscores, but that would have conflicted
    with C++'s user-defined literals.)

    I wonder why; user-defined literals for names start with alpha or
    underscore, no? - Where's the conflict?

    Janis

    [...]


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Sat Mar 28 10:09:26 2026
    On 28/03/2026 05:17, Janis Papanagnou wrote:
    On 2026-03-28 04:41, Keith Thompson wrote:
    Lawrence D?Oliveiro <ldo@nz.invalid> writes:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M”llers wrote:

    ˙˙˙˙˙ diffns += 1000000000UL;

    Can you write

    ˙˙˙˙˙˙ diffns += 1_000_000_000UL;

    yet?

    Not in C.˙ C23 introduces the apostrophe as a digit separator, copied
    from C++:

    ˙˙˙˙˙˙ diffns += 1'000'000'000UL;

    I think that's fine, much better than parsing those huge numbers.
    (A convention used in Switzerland, IIRC.)


    (I would have preferred underscores, but that would have conflicted
    with C++'s user-defined literals.)

    I wonder why; user-defined literals for names start with alpha or
    underscore, no? - Where's the conflict?


    123_456 would, in C++, be parsed as the integer constant 123 then the user-defined literal identifier _456. Thus C++ could not use underscore
    as a digit separator, and choose apostrophes instead. C23 followed that because there is a strong preference for keeping consistency between the languages for common features. (And maybe someone will want to add user-defined literals of some kind to C in the future.)


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Bart@3:633/10 to All on Sat Mar 28 11:33:12 2026
    On 28/03/2026 09:09, David Brown wrote:
    On 28/03/2026 05:17, Janis Papanagnou wrote:
    On 2026-03-28 04:41, Keith Thompson wrote:
    Lawrence D?Oliveiro <ldo@nz.invalid> writes:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M”llers wrote:

    ˙˙˙˙˙ diffns += 1000000000UL;

    Can you write

    ˙˙˙˙˙˙ diffns += 1_000_000_000UL;

    yet?

    Not in C.˙ C23 introduces the apostrophe as a digit separator, copied
    from C++:

    ˙˙˙˙˙˙ diffns += 1'000'000'000UL;

    I think that's fine, much better than parsing those huge numbers.
    (A convention used in Switzerland, IIRC.)


    (I would have preferred underscores, but that would have conflicted
    with C++'s user-defined literals.)

    I wonder why; user-defined literals for names start with alpha or
    underscore, no? - Where's the conflict?


    123_456 would, in C++, be parsed as the integer constant 123 then the user-defined literal identifier _456.˙ Thus C++ could not use underscore
    as a digit separator, and choose apostrophes instead.˙ C23 followed that because there is a strong preference for keeping consistency between the languages for common features.˙ (And maybe someone will want to add user-defined literals of some kind to C in the future.)


    Would 123 _456 (with intervening white-space) be meaningful in any of
    C++'s syntax? That is, a numeric literal followed by an identifier.

    If not then the lexical grammar could have been changed so that
    underlines could be part of numeric literals, just not at the start.

    (I hadn't realised until now that _1234 is a valid identifier in C. Fortunately most haven't either, or sensibly avoid it.)

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Scott Lurndal@3:633/10 to All on Sat Mar 28 15:14:42 2026
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence D?Oliveiro <ldo@nz.invalid> writes:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M”llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator, copied
    from C++:

    diffns += 1'000'000'000UL;

    Or diffns += 1000ul * 1000ul * 1000ul;

    or diffns += 1 * NS_PER_SEC;

    with
    #define NS_PER_SEC ((1000ul * 1000ul * 1000ul))


    (I would have preferred underscores, but that would have conflicted
    with C++'s user-defined literals.)

    Likewise, I'd prefer the underscore. IIRC, that's what is used
    in Verilog.


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Sat Mar 28 16:35:29 2026
    On 28/03/2026 12:33, Bart wrote:
    On 28/03/2026 09:09, David Brown wrote:
    On 28/03/2026 05:17, Janis Papanagnou wrote:
    On 2026-03-28 04:41, Keith Thompson wrote:
    Lawrence D?Oliveiro <ldo@nz.invalid> writes:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M”llers wrote:

    ˙˙˙˙˙ diffns += 1000000000UL;

    Can you write

    ˙˙˙˙˙˙ diffns += 1_000_000_000UL;

    yet?

    Not in C.˙ C23 introduces the apostrophe as a digit separator, copied
    from C++:

    ˙˙˙˙˙˙ diffns += 1'000'000'000UL;

    I think that's fine, much better than parsing those huge numbers.
    (A convention used in Switzerland, IIRC.)


    (I would have preferred underscores, but that would have conflicted
    with C++'s user-defined literals.)

    I wonder why; user-defined literals for names start with alpha or
    underscore, no? - Where's the conflict?


    123_456 would, in C++, be parsed as the integer constant 123 then the
    user-defined literal identifier _456.˙ Thus C++ could not use
    underscore as a digit separator, and choose apostrophes instead.˙ C23
    followed that because there is a strong preference for keeping
    consistency between the languages for common features.˙ (And maybe
    someone will want to add user-defined literals of some kind to C in
    the future.)


    Would 123 _456 (with intervening white-space) be meaningful in any of C+
    +'s syntax? That is, a numeric literal followed by an identifier.

    It would be interpreted as two tokens. So in this case, it is unlikely
    to be meaningful unless you first had "#define _456 +1", or something
    like that. Just like for C.


    If not then the lexical grammar could have been changed so that
    underlines could be part of numeric literals, just not at the start.


    Certainly C++ could have be defined to make _ part of the numeric
    literal syntax.

    (I hadn't realised until now that _1234 is a valid identifier in C. Fortunately most haven't either, or sensibly avoid it.)

    Well, underscore basically counts as a letter, so it's a valid
    identifier just like "x1234" would be. Sometimes people use identifiers
    like that for specific purposes, like macro parameters.



    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Richard Harnden@3:633/10 to All on Sat Mar 28 16:56:53 2026
    On 28/03/2026 15:35, David Brown wrote:
    On 28/03/2026 12:33, Bart wrote:
    On 28/03/2026 09:09, David Brown wrote:
    On 28/03/2026 05:17, Janis Papanagnou wrote:
    On 2026-03-28 04:41, Keith Thompson wrote:
    Lawrence D?Oliveiro <ldo@nz.invalid> writes:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M”llers wrote:

    ˙˙˙˙˙ diffns += 1000000000UL;

    Can you write

    ˙˙˙˙˙˙ diffns += 1_000_000_000UL;

    yet?

    Not in C.˙ C23 introduces the apostrophe as a digit separator, copied >>>>> from C++:

    ˙˙˙˙˙˙ diffns += 1'000'000'000UL;

    I think that's fine, much better than parsing those huge numbers.
    (A convention used in Switzerland, IIRC.)


    (I would have preferred underscores, but that would have conflicted
    with C++'s user-defined literals.)

    I wonder why; user-defined literals for names start with alpha or
    underscore, no? - Where's the conflict?


    123_456 would, in C++, be parsed as the integer constant 123 then the
    user-defined literal identifier _456.˙ Thus C++ could not use
    underscore as a digit separator, and choose apostrophes instead.˙ C23
    followed that because there is a strong preference for keeping
    consistency between the languages for common features.˙ (And maybe
    someone will want to add user-defined literals of some kind to C in
    the future.)


    Would 123 _456 (with intervening white-space) be meaningful in any of
    C+ +'s syntax? That is, a numeric literal followed by an identifier.

    It would be interpreted as two tokens.˙ So in this case, it is unlikely
    to be meaningful unless you first had "#define _456 +1", or something
    like that.˙ Just like for C.


    If not then the lexical grammar could have been changed so that
    underlines could be part of numeric literals, just not at the start.


    Certainly C++ could have be defined to make _ part of the numeric
    literal syntax.

    (I hadn't realised until now that _1234 is a valid identifier in C.
    Fortunately most haven't either, or sensibly avoid it.)

    Well, underscore basically counts as a letter, so it's a valid
    identifier just like "x1234" would be.˙ Sometimes people use identifiers like that for specific purposes, like macro parameters.




    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Richard Harnden@3:633/10 to All on Sat Mar 28 16:58:23 2026
    On 28/03/2026 15:35, David Brown wrote:
    Well, underscore basically counts as a letter, so it's a valid
    identifier just like "x1234" would be.˙ Sometimes people use identifiers like that for specific purposes, like macro parameters.

    Isn't _UPPERCASE and __anything reserved for the implementation?



    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Sat Mar 28 10:18:40 2026
    scott@slp53.sl.home (Scott Lurndal) writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence Dƒ??Oliveiro <ldo@nz.invalid> writes:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M??llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator, copied
    from C++:

    diffns += 1'000'000'000UL;

    Or diffns += 1000ul * 1000ul * 1000ul;

    or diffns += 1 * NS_PER_SEC;

    with
    #define NS_PER_SEC ((1000ul * 1000ul * 1000ul))

    Why the "1 *"? And why two sets of parentheses?

    An integer constant is always of a type big enough to hold its value.
    The same does not hold for larger expressions. It doesn't matter in
    this case, since ULONG_MAX is guaranteed to be bigger than
    1'000'000'000, but it can be a problem in more general cases.

    (I would have preferred underscores, but that would have conflicted
    with C++'s user-defined literals.)

    Likewise, I'd prefer the underscore. IIRC, that's what is used
    in Verilog.

    And Python, and Perl, and Ada, and a number of other languages.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Josef MĂśllers@3:633/10 to All on Sat Mar 28 21:58:47 2026
    On 27.03.26 17:02, Scott Lurndal wrote:
    =?UTF-8?Q?Josef_M=C3=B6llers?= <josef@invalid.invalid> writes:
    On 27.03.26 05:46, Janis Papanagnou wrote:
    Subject: Why is this happening?

    I think because you are doing wrong calculations here:

    > return ((stop.tv_sec-started.tv_sec) + (stop.tv_nsec-
    started.tv_nsec)) / B;

    You should not subtract the components s/ns separately when scaling.
    Instead build the float stop number and started number separately and
    then subtract.

    I usually subtract the nsec parts and if the result is negative, adjust
    the sec and the nsec parts accordingly:

    I don't use floating point when unsigned integers are most
    appropriate (which describes the actually implementation of
    tv_sec/tv_nsec on pretty much every single implementation
    in existence). For printing, just scale the unsigned
    integer appropriately.

    I just print using "%u.%09u".

    Josef

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From James Kuyper@3:633/10 to All on Sat Mar 28 19:24:12 2026
    On 2026-03-28 12:58, Richard Harnden wrote:
    On 28/03/2026 15:35, David Brown wrote:
    Well, underscore basically counts as a letter, so it's a valid
    identifier just like "x1234" would be.˙ Sometimes people use
    identifiers like that for specific purposes, like macro parameters.

    Isn't _UPPERCASE and __anything reserved for the implementation?

    Correct. But _1234 fits neither of those categories. It does fit a third category:

    "All identifiers that begin with an underscore are reserved for use as identifiers with file scope in both the ordinary and tag name spaces." (6.4.3.1p7).

    However, you can still define such identifiers in other scopes, or in
    other name spaces. As far as I can tell, none of those possibilities
    helps in this particular case.


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Tim Rentsch@3:633/10 to All on Sat Mar 28 19:12:05 2026
    scott@slp53.sl.home (Scott Lurndal) writes:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Lawrence D <<E2>> ??Oliveiro <ldo@nz.invalid> writes:

    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M@C3{B6}llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator, copied
    from C++:

    diffns += 1'000'000'000UL;

    Or diffns += 1000ul * 1000ul * 1000ul;

    or diffns += 1 * NS_PER_SEC;

    with
    #define NS_PER_SEC ((1000ul * 1000ul * 1000ul))

    (I would have preferred underscores, but that would have conflicted
    with C++'s user-defined literals.)

    Likewise, I'd prefer the underscore.

    Ditto. And there is no reason C could have allowed both,
    and C++ be damned.

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Sat Mar 28 22:31:46 2026
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence D <<E2>> ??Oliveiro <ldo@nz.invalid> writes:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M@C3{B6}llers wrote:
    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator, copied
    from C++:

    diffns += 1'000'000'000UL;

    Or diffns += 1000ul * 1000ul * 1000ul;

    or diffns += 1 * NS_PER_SEC;

    with
    #define NS_PER_SEC ((1000ul * 1000ul * 1000ul))

    (I would have preferred underscores, but that would have conflicted
    with C++'s user-defined literals.)

    Likewise, I'd prefer the underscore.

    Ditto. And there is no reason C could have allowed both,
    and C++ be damned.

    (I think you omitted a "not".)

    Using apostrophes is IMHO far better than either allowing two
    arbitrarily distinct syntaxes or a gratuitous incompatibility
    with C++.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Michael S@3:633/10 to All on Sun Mar 29 11:50:57 2026
    On Sat, 28 Mar 2026 15:14:42 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence D?Oliveiro <ldo@nz.invalid> writes:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M_?llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator, copied
    from C++:

    diffns += 1'000'000'000UL;

    Or diffns += 1000ul * 1000ul * 1000ul;

    or diffns += 1 * NS_PER_SEC;

    with
    #define NS_PER_SEC ((1000ul * 1000ul * 1000ul))

    Why not (int)1e9 ?



    (I would have preferred underscores, but that would have conflicted
    with C++'s user-defined literals.)

    Likewise, I'd prefer the underscore. IIRC, that's what is used
    in Verilog.




    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Sun Mar 29 11:33:39 2026
    On 28/03/2026 17:58, Richard Harnden wrote:
    On 28/03/2026 15:35, David Brown wrote:
    Well, underscore basically counts as a letter, so it's a valid
    identifier just like "x1234" would be.˙ Sometimes people use
    identifiers like that for specific purposes, like macro parameters.

    Isn't _UPPERCASE and __anything reserved for the implementation?



    Yes.

    And identifiers with _lowercase have implicit internal linkage (when
    they would otherwise have had implicit external linkage). That's why I
    wrote "underscore /basically/ counts as a letter" - to save mentioning
    all the details.


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Janis Papanagnou@3:633/10 to All on Sun Mar 29 14:30:27 2026
    On 2026-03-28 21:58, Josef M”llers wrote:
    On 27.03.26 17:02, Scott Lurndal wrote:
    =?UTF-8?Q?Josef_M=C3=B6llers?= <josef@invalid.invalid> writes:
    On 27.03.26 05:46, Janis Papanagnou wrote:
    Subject: Why is this happening?

    I think because you are doing wrong calculations here:

    ˙ > return ((stop.tv_sec-started.tv_sec) + (stop.tv_nsec-
    started.tv_nsec)) / B;

    You should not subtract the components s/ns separately when scaling.
    Instead build the float stop number and started number separately and
    then subtract.

    I usually subtract the nsec parts and if the result is negative, adjust
    the sec and the nsec parts accordingly:

    That's fine if you operate on the integer parts separately. (I'm
    sometimes doing a similar thing if I'm working with the integral
    components of a calendar date, for example.)

    Generally I prefer to use types that fit the element I'm operating
    on. That's why I prefer to express dT = stop_time - start_time
    in the case above as
    (stop_s + F * stop_ns) - (start_s + F * start_ns) with F=1e-9
    to easily see the application entities and logic.

    I think that's the clearest expression, and it's an expression
    without conditional. (A habit from the early days of programming
    where conditionals were suboptimal. Nowadays it's meaningless,
    and huge amounts of time wasted at other places; using suboptimal
    algorithms, or over-complicated processes, or just bloat.) The
    expressions in your variant appear to me unnecessary confusing
    with using '1000000000UL', for example. - As said, basically a
    matter of personal preference, despite the rationale of clarity,
    which is also mostly subjective.

    I don't use floating point when unsigned integers are most
    appropriate (which describes the actually implementation of
    tv_sec/tv_nsec on pretty much every single implementation
    in existence).˙ For printing, just scale the unsigned
    integer appropriately.

    I just print using "%u.%09u".

    Depending on the application case; if I want flexibility to display milliseconds and microseconds as well formatting a single FP-number
    appears to be clearer and easier to handle (e.g. than dividing the
    printf's 'int' argument in those cases), including any rounding
    that would typically also be desired. (Even simple things can lead
    to messy code if you choose an inappropriate data representation.)

    Janis


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Richard Harnden@3:633/10 to All on Sun Mar 29 16:30:23 2026
    On 29/03/2026 10:33, David Brown wrote:
    On 28/03/2026 17:58, Richard Harnden wrote:
    On 28/03/2026 15:35, David Brown wrote:
    Well, underscore basically counts as a letter, so it's a valid
    identifier just like "x1234" would be.˙ Sometimes people use
    identifiers like that for specific purposes, like macro parameters.

    Isn't _UPPERCASE and __anything reserved for the implementation?



    Yes.

    And identifiers with _lowercase have implicit internal linkage (when
    they would otherwise have had implicit external linkage).˙ That's why I wrote "underscore /basically/ counts as a letter" - to save mentioning
    all the details.


    I didn't know that, thanks.

    So, at file scope, these are equivalent ... ?
    static int foo;
    int _foo;

    Is _foo initialised to zero?


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Tim Rentsch@3:633/10 to All on Sun Mar 29 10:37:23 2026
    Richard Harnden <richard.nospam@gmail.invalid> writes:

    On 29/03/2026 10:33, David Brown wrote:

    On 28/03/2026 17:58, Richard Harnden wrote:

    On 28/03/2026 15:35, David Brown wrote:

    Well, underscore basically counts as a letter, so it's a valid
    identifier just like "x1234" would be. Sometimes people use
    identifiers like that for specific purposes, like macro
    parameters.

    Isn't _UPPERCASE and __anything reserved for the implementation?

    Yes.

    And identifiers with _lowercase have implicit internal linkage (when
    they would otherwise have had implicit external linkage). That's
    why I wrote "underscore /basically/ counts as a letter" - to save
    mentioning all the details.

    I didn't know that, thanks.

    Don't believe everything you read. Of course, as far as the C
    standard is concerned, defining a reserved name is undefined
    behavior, but actual compilers have different behavior than what
    is suggested above.

    So, at file scope, these are equivalent ... ?
    static int foo;
    int _foo;

    If you try with gcc or clang (which I did), I expect you will
    find that _foo is an ordinary global symbol. It does not have
    "implicit internal linkage". It is treated just like any other
    external definition.


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Scott Lurndal@3:633/10 to All on Sun Mar 29 18:50:03 2026
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence Dƒ??Oliveiro <ldo@nz.invalid> writes:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M??llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator, copied >>>from C++:

    diffns += 1'000'000'000UL;

    Or diffns += 1000ul * 1000ul * 1000ul;

    or diffns += 1 * NS_PER_SEC;

    with
    #define NS_PER_SEC ((1000ul * 1000ul * 1000ul))

    Why the "1 *"? And why two sets of parentheses?

    a) Because I usually use a variable there.
    b) Korn Shell syntax for arithmetic expressions
    when typing on auto-pilot.


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Scott Lurndal@3:633/10 to All on Sun Mar 29 18:56:38 2026
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 2026-03-28 21:58, Josef M”llers wrote:
    On 27.03.26 17:02, Scott Lurndal wrote:
    =?UTF-8?Q?Josef_M=C3=B6llers?= <josef@invalid.invalid> writes:
    On 27.03.26 05:46, Janis Papanagnou wrote:
    Subject: Why is this happening?

    I think because you are doing wrong calculations here:

    ˙ > return ((stop.tv_sec-started.tv_sec) + (stop.tv_nsec-
    started.tv_nsec)) / B;

    You should not subtract the components s/ns separately when scaling. >>>>> Instead build the float stop number and started number separately and >>>>> then subtract.

    I usually subtract the nsec parts and if the result is negative, adjust >>>> the sec and the nsec parts accordingly:

    That's fine if you operate on the integer parts separately. (I'm
    sometimes doing a similar thing if I'm working with the integral
    components of a calendar date, for example.)

    Generally I prefer to use types that fit the element I'm operating
    on. That's why I prefer to express dT = stop_time - start_time
    in the case above as
    (stop_s + F * stop_ns) - (start_s + F * start_ns) with F=1e-9
    to easily see the application entities and logic.

    My formative years were writing operating system code. For
    various reasons floating point was prohibited in OS code
    (I believe this is still true for linux x86 - which doesn't
    bother saving the FP state on context switches or interrupts
    unless it has actually been used since the last context
    switch).

    In those days (70s, 80s), floating point was often optional,
    and when present did not perform as well as integer
    arithmetic.

    I still avoid floating point when it isn't necessary just
    to reduce system call overhead by a small amount.


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Chris M. Thomasson@3:633/10 to All on Sun Mar 29 13:19:57 2026
    On 3/29/2026 2:33 AM, David Brown wrote:
    On 28/03/2026 17:58, Richard Harnden wrote:
    On 28/03/2026 15:35, David Brown wrote:
    Well, underscore basically counts as a letter, so it's a valid
    identifier just like "x1234" would be.˙ Sometimes people use
    identifiers like that for specific purposes, like macro parameters.

    Isn't _UPPERCASE and __anything reserved for the implementation?



    Yes.

    And identifiers with _lowercase have implicit internal linkage (when
    they would otherwise have had implicit external linkage).˙ That's why I wrote "underscore /basically/ counts as a letter" - to save mentioning
    all the details.


    Actually, I remember back in the day when I used to use _this. Some
    people said it is actually "okay", then I switched to self...

    struct foo
    {
    int bar;
    };


    void foo_init(struct foo* _this);

    vs

    void foo_init(struct foo* self);


    Now, lets ponder on *_t?

    struct foo_t ?

    intrude into POSIX?

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Chris M. Thomasson@3:633/10 to All on Sun Mar 29 13:26:47 2026
    On 3/29/2026 1:19 PM, Chris M. Thomasson wrote:
    On 3/29/2026 2:33 AM, David Brown wrote:
    On 28/03/2026 17:58, Richard Harnden wrote:
    On 28/03/2026 15:35, David Brown wrote:
    Well, underscore basically counts as a letter, so it's a valid
    identifier just like "x1234" would be.˙ Sometimes people use
    identifiers like that for specific purposes, like macro parameters.

    Isn't _UPPERCASE and __anything reserved for the implementation?



    Yes.

    And identifiers with _lowercase have implicit internal linkage (when
    they would otherwise have had implicit external linkage).˙ That's why
    I wrote "underscore /basically/ counts as a letter" - to save
    mentioning all the details.


    Actually, I remember back in the day when I used to use _this. Some
    people said it is actually "okay", then I switched to self...

    struct foo
    {
    ˙˙˙ int bar;
    };


    void foo_init(struct foo* _this);

    vs

    void foo_init(struct foo* self);


    Now, lets ponder on *_t?

    struct foo_t ?

    intrude into POSIX?

    I like x_y_z, say foolib_read_types where x = foolib, y = read, z = types?

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Sun Mar 29 13:54:47 2026
    Michael S <already5chosen@yahoo.com> writes:
    On Sat, 28 Mar 2026 15:14:42 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence D???Oliveiro <ldo@nz.invalid> writes:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M_?llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator, copied
    from C++:

    diffns += 1'000'000'000UL;

    Or diffns += 1000ul * 1000ul * 1000ul;

    or diffns += 1 * NS_PER_SEC;

    with
    #define NS_PER_SEC ((1000ul * 1000ul * 1000ul))

    Why not (int)1e9 ?
    [...]

    Because int is not guaranteed to be wider than 16 bits (though if
    you're already relying on Windows or POSIX, you can assume it's at
    least 32 bits). The original expression was of type unsigned long,
    so (unsigned long)1e9 would be more nearly correct.

    And because it's a floating-point to integer conversion in a
    context that doesn't need floating-point. I'm not sure whether
    (unsigned long)1e9 is actually guaranteed to yield 1000000000 rather
    than 999999999. Maybe it is, but I don't want to waste brain cells
    proving it.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Sun Mar 29 13:57:41 2026
    David Brown <david.brown@hesbynett.no> writes:
    On 28/03/2026 17:58, Richard Harnden wrote:
    On 28/03/2026 15:35, David Brown wrote:
    Well, underscore basically counts as a letter, so it's a valid
    identifier just like "x1234" would be.˙ Sometimes people use
    identifiers like that for specific purposes, like macro parameters.
    Isn't _UPPERCASE and __anything reserved for the implementation?

    Yes.

    And identifiers with _lowercase have implicit internal linkage (when
    they would otherwise have had implicit external linkage). That's why
    I wrote "underscore /basically/ counts as a letter" - to save
    mentioning all the details.

    I don't believe that's correct. The language defines rules about
    which identifiers are reserved depending on how they're spelled,
    but I've never seen a rule that says the linkage of an identifier
    is affected by its spelling. (A compiler could take advantage of
    undefined behavior to do something weird, but I believe and hope
    that no compilers actually do so.)

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Sun Mar 29 14:14:47 2026
    "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes:
    [...]
    Now, lets ponder on *_t?

    struct foo_t ?

    intrude into POSIX?

    I don't know. I know that POSIX reserves the _t suffix for type
    names, but I haven't been able to find the actual requirement in
    the POSIX standard. It would depend on the exact wording.

    In "struct foo_t", "foo_t is not a type name, but "struct foo_t" is.

    I wouldn't use a "_t" suffix on a struct tag. The required "struct"
    keyword is enough to indicate that it's a type.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Tim Rentsch@3:633/10 to All on Sun Mar 29 14:43:52 2026
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Lawrence D <<E2>> ??Oliveiro <ldo@nz.invalid> writes:

    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M@C3{B6}llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator,
    copied from C++:

    diffns += 1'000'000'000UL;

    Or diffns += 1000ul * 1000ul * 1000ul;

    or diffns += 1 * NS_PER_SEC;

    with
    #define NS_PER_SEC ((1000ul * 1000ul * 1000ul))

    (I would have preferred underscores, but that would have
    conflicted with C++'s user-defined literals.)

    Likewise, I'd prefer the underscore.

    Ditto. And there is no reason C could have allowed both,
    and C++ be damned.

    Of course I meant there is no reason C couldn't have allowed
    both. Sorry for any confusion.

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Michael S@3:633/10 to All on Mon Mar 30 02:05:23 2026
    On Sun, 29 Mar 2026 13:54:47 -0700
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:

    Michael S <already5chosen@yahoo.com> writes:
    On Sat, 28 Mar 2026 15:14:42 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence D???Oliveiro <ldo@nz.invalid> writes:

    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M_?llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator,
    copied from C++:

    diffns += 1'000'000'000UL;

    Or diffns += 1000ul * 1000ul * 1000ul;

    or diffns += 1 * NS_PER_SEC;

    with
    #define NS_PER_SEC ((1000ul * 1000ul * 1000ul))

    Why not (int)1e9 ?
    [...]

    Because int is not guaranteed to be wider than 16 bits (though if
    you're already relying on Windows or POSIX, you can assume it's at
    least 32 bits). The original expression was of type unsigned long,
    so (unsigned long)1e9 would be more nearly correct.

    And because it's a floating-point to integer conversion in a
    context that doesn't need floating-point. I'm not sure whether
    (unsigned long)1e9 is actually guaranteed to yield 1000000000 rather
    than 999999999. Maybe it is, but I don't want to waste brain cells
    proving it.


    IEEE binary64 has precise representations for all powers of 10 from 1e0
    to 1e22. I.e it covers all powers of 10 that fit within 64-bit unsigned
    integer with 3 values to spare.









    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Sun Mar 29 16:22:10 2026
    Michael S <already5chosen@yahoo.com> writes:
    On Sun, 29 Mar 2026 13:54:47 -0700
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    Michael S <already5chosen@yahoo.com> writes:
    On Sat, 28 Mar 2026 15:14:42 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence D???Oliveiro <ldo@nz.invalid> writes:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M_?llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator,
    copied from C++:

    diffns += 1'000'000'000UL;

    Or diffns += 1000ul * 1000ul * 1000ul;

    or diffns += 1 * NS_PER_SEC;

    with
    #define NS_PER_SEC ((1000ul * 1000ul * 1000ul))

    Why not (int)1e9 ?
    [...]

    Because int is not guaranteed to be wider than 16 bits (though if
    you're already relying on Windows or POSIX, you can assume it's at
    least 32 bits). The original expression was of type unsigned long,
    so (unsigned long)1e9 would be more nearly correct.

    And because it's a floating-point to integer conversion in a
    context that doesn't need floating-point. I'm not sure whether
    (unsigned long)1e9 is actually guaranteed to yield 1000000000 rather
    than 999999999. Maybe it is, but I don't want to waste brain cells
    proving it.

    IEEE binary64 has precise representations for all powers of 10 from 1e0
    to 1e22. I.e it covers all powers of 10 that fit within 64-bit unsigned integer with 3 values to spare.

    Sure, but the C standard doesn't guarantee IEEE-compatible
    floating-point.

    I'd be very surprised if any C implementation had (unsigned long)1e9
    unequal to 1000000000. If I ran across one, I'd seriously consider
    submitting a bug report. I'd have to study the C standard's
    floating-point requirements to be sure (I haven't done that yet).

    My point is that writing (unsigned long)1e9 rather than 1000000000 or
    (1000ul * 1000ul * 1000ul) introduces complications I'd rather avoid.
    It *might* be perfectly safe, but I'm uncomfortable relying on it.
    If nothing else, if the program misbehaves, it's one less thing to
    worry about while tracking down the bug.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Mike Terry@3:633/10 to All on Mon Mar 30 00:41:57 2026
    On 29/03/2026 13:30, Janis Papanagnou wrote:
    On 2026-03-28 21:58, Josef M?llers wrote:
    On 27.03.26 17:02, Scott Lurndal wrote:
    =?UTF-8?Q?Josef_M=C3=B6llers?= <josef@invalid.invalid> writes:
    On 27.03.26 05:46, Janis Papanagnou wrote:
    Subject: Why is this happening?

    I think because you are doing wrong calculations here:

    ? > return ((stop.tv_sec-started.tv_sec) + (stop.tv_nsec-
    started.tv_nsec)) / B;

    You should not subtract the components s/ns separately when scaling. >>>>> Instead build the float stop number and started number separately and >>>>> then subtract.

    I usually subtract the nsec parts and if the result is negative, adjust >>>> the sec and the nsec parts accordingly:

    That's fine if you operate on the integer parts separately. (I'm
    sometimes doing a similar thing if I'm working with the integral
    components of a calendar date, for example.)

    Generally I prefer to use types that fit the element I'm operating
    on. That's why I prefer to express? dT = stop_time - start_time
    in the case above as
    ? (stop_s + F * stop_ns) - (start_s + F * start_ns)?? with F=1e-9
    to easily see the application entities and logic.

    I think that's the clearest expression, and it's an expression
    without conditional. (A habit from the early days of programming
    where conditionals were suboptimal. Nowadays it's meaningless,
    and huge amounts of time wasted at other places; using suboptimal
    algorithms, or over-complicated processes, or just bloat.) The
    expressions in your variant appear to me unnecessary confusing
    with using '1000000000UL', for example. - As said, basically a
    matter of personal preference, despite the rationale of clarity,
    which is also mostly subjective.

    We have a calculation here, which ignoring precision issues is of the form

    (A1 + A2) - (B1 + B2)

    The magnitudes are such that A1,B1 are some order of magnitude greater than A2,B2, but the
    differences A1-B1, A2-B2 are of broadly similar magnitude (in the scenario we're considering). If
    we were using a single integral type for everything, or some kind of infinite precision real
    numbers, the order of calculation would not matter, but floating point is not like that - the order
    of calculation can give different results, due to the finite precision limits.

    In such a situation, it's surely good practice to subtract the components of similar magnitude
    first, then add the results, as this avoids unnecessarily dropping the precision of the final
    result. That seems more important than how subjectively clear the expression might look to someone. :)

    So I'd go with the original (A1-B1) + (A2-B2) expression, even if someone does some calculation to
    show that on a particular architecture, with the actual float/time types being used, the
    "logical/clearest expression" ordering ((A1+A2) - (B1+B2)) is /sufficiently/ precise for purposes.


    Mike.


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Janis Papanagnou@3:633/10 to All on Mon Mar 30 02:00:28 2026
    On 2026-03-29 20:56, Scott Lurndal wrote:
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    [...]

    My formative years were writing operating system code. For
    various reasons floating point was prohibited in OS code
    (I believe this is still true for linux x86 - which doesn't
    bother saving the FP state on context switches or interrupts
    unless it has actually been used since the last context
    switch).

    In those days (70s, 80s), floating point was often optional,
    and when present did not perform as well as integer
    arithmetic.

    I still avoid floating point when it isn't necessary just
    to reduce system call overhead by a small amount.

    With all what I said, I can still agree with your points!
    Whenever I can prevent introducing floats unnecessarily I'd
    do that. There are even behavioral examples in contemporary
    software, concerning windowing move and resize anomalies,
    where I suspected that these effects can only be explained
    by the developers having used FP-arithmetic instead of the
    plain and exact integer representation of window resolution.
    (Though I haven't verified my suspicion by code inspection.)
    In the case of a real-typed time value the splitting appears
    to me to be artificial, though. In another case, where I had
    a fractional time to be passed by an argument to my program,
    I read in the sss.fff time as two integer and fed two separate
    functions, sleep() and usleep(), with the two numbers; AFAIR
    I wasn't sure from the man-page whether usleep() would allow
    seconds and how many; i.e. whether there are guarantees for
    the supported range of useconds_t. So my use of types depends
    on the concrete application.

    Janis


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From James Kuyper@3:633/10 to All on Sun Mar 29 20:47:49 2026
    On 2026-03-29 17:14, Keith Thompson wrote:
    "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes:
    [...]
    Now, lets ponder on *_t?

    struct foo_t ?

    intrude into POSIX?

    I don't know. I know that POSIX reserves the _t suffix for type
    names, but I haven't been able to find the actual requirement in
    the POSIX standard. It would depend on the exact wording.

    Section 2.2.2 "The Name Space" has a table listing headers and their corresponding reserved identifiers. The very last entry in the table
    applies to "any header" and specifies a suffix of "_t". This doesn't
    identify the purpose for which it is reserved - which might be explained elsewhere.





    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Janis Papanagnou@3:633/10 to All on Mon Mar 30 09:25:39 2026
    On 2026-03-30 01:41, Mike Terry wrote:
    On 29/03/2026 13:30, Janis Papanagnou wrote:
    On 2026-03-28 21:58, Josef M”llers wrote:
    On 27.03.26 17:02, Scott Lurndal wrote:
    =?UTF-8?Q?Josef_M=C3=B6llers?= <josef@invalid.invalid> writes:
    On 27.03.26 05:46, Janis Papanagnou wrote:
    Subject: Why is this happening?

    I think because you are doing wrong calculations here:

    ˙ > return ((stop.tv_sec-started.tv_sec) + (stop.tv_nsec-
    started.tv_nsec)) / B;

    You should not subtract the components s/ns separately when scaling. >>>>>> Instead build the float stop number and started number separately and >>>>>> then subtract.

    I usually subtract the nsec parts and if the result is negative,
    adjust
    the sec and the nsec parts accordingly:

    That's fine if you operate on the integer parts separately. (I'm
    sometimes doing a similar thing if I'm working with the integral
    components of a calendar date, for example.)

    Generally I prefer to use types that fit the element I'm operating
    on. That's why I prefer to express˙ dT = stop_time - start_time
    in the case above as
    ˙˙ (stop_s + F * stop_ns) - (start_s + F * start_ns)˙˙ with F=1e-9
    to easily see the application entities and logic.

    I think that's the clearest expression, and it's an expression
    without conditional. (A habit from the early days of programming
    where conditionals were suboptimal. Nowadays it's meaningless,
    and huge amounts of time wasted at other places; using suboptimal
    algorithms, or over-complicated processes, or just bloat.) The
    expressions in your variant appear to me unnecessary confusing
    with using '1000000000UL', for example. - As said, basically a
    matter of personal preference, despite the rationale of clarity,
    which is also mostly subjective.

    We have a calculation here, which ignoring precision issues is of the form

    ˙˙ (A1˙ +˙ A2)˙ -˙ (B1˙ +˙ B2)

    The magnitudes are such that A1,B1 are some order of magnitude greater
    than A2,B2, but the differences A1-B1, A2-B2 are of broadly similar magnitude (in the scenario we're considering).˙ If we were using a
    single integral type for everything, or some kind of infinite precision
    real numbers, the order of calculation would not matter, but floating
    point is not like that - the order of calculation can give different results, due to the finite precision limits.

    In such a situation, it's surely good practice to subtract the
    components of similar magnitude first, then add the results, as this
    avoids unnecessarily dropping the precision of the final result.˙ That
    seems more important than how subjectively clear the expression might
    look to someone. :)

    So I'd go with the original (A1-B1) + (A2-B2) expression, even if
    someone does some calculation to show that on a particular architecture, with the actual float/time types being used, the "logical/clearest expression" ordering ((A1+A2) - (B1+B2)) is /sufficiently/ precise for purposes.

    Mike, I see where you're coming from; from numerical mathematics. In
    cases where you have to accumulate many values of different magnitude
    what you describe is necessary to not lose the values of minor value
    in the final sum, since a large amount of such values may contribute.
    Here we were calculating run-times. A "problem" arises if you cannot
    represent huge seconds values combined with high resolution nano-sec
    values in one, say, double variable. If one thinks that, say, with
    runtime of minutes or hours the least nanoseconds resolution is (for
    your case) of interest you may do that. (And mind that we're still
    not accumulating many such values!) But usually an IEEE double float
    with 64 bit and ~16 decimal figures should suffice for that purpose.
    YMMV. For me, having seen a lot of good and bad code, clarity of code
    is an essential software property so I'd not unnecessarily muddy the
    code for a requirement we actually don't seem to have (in this case).

    Janis


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Michael S@3:633/10 to All on Mon Mar 30 10:57:36 2026
    On Sun, 29 Mar 2026 16:22:10 -0700
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:

    Michael S <already5chosen@yahoo.com> writes:
    On Sun, 29 Mar 2026 13:54:47 -0700
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    Michael S <already5chosen@yahoo.com> writes:
    On Sat, 28 Mar 2026 15:14:42 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence D???Oliveiro <ldo@nz.invalid> writes
    :
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M_?llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator,
    copied from C++:

    diffns += 1'000'000'000UL;

    Or diffns += 1000ul * 1000ul * 1000ul;

    or diffns += 1 * NS_PER_SEC;

    with
    #define NS_PER_SEC ((1000ul * 1000ul * 1000ul))

    Why not (int)1e9 ?
    [...]

    Because int is not guaranteed to be wider than 16 bits (though if
    you're already relying on Windows or POSIX, you can assume it's at
    least 32 bits). The original expression was of type unsigned long,
    so (unsigned long)1e9 would be more nearly correct.

    And because it's a floating-point to integer conversion in a
    context that doesn't need floating-point. I'm not sure whether
    (unsigned long)1e9 is actually guaranteed to yield 1000000000
    rather than 999999999. Maybe it is, but I don't want to waste
    brain cells proving it.

    IEEE binary64 has precise representations for all powers of 10 from
    1e0 to 1e22. I.e it covers all powers of 10 that fit within 64-bit
    unsigned integer with 3 values to spare.

    Sure, but the C standard doesn't guarantee IEEE-compatible
    floating-point.


    I am not in the racket of uber-portable. Don't want to be accused of trespassing into pasture of James K.

    I'd be very surprised if any C implementation had (unsigned long)1e9
    unequal to 1000000000. If I ran across one, I'd seriously consider submitting a bug report. I'd have to study the C standard's
    floating-point requirements to be sure (I haven't done that yet).


    I know one environment where bug of that sort could happen, but not for
    1e9. It could happen for 1e19, which is a border-line case (it fits in uint64_t, but does not fit in int64_t).
    However environment in question is not C. C compiler from the same
    vendor (MS, if you wonder) handles (uint64_t)1e19 just fine.

    My point is that writing (unsigned long)1e9 rather than 1000000000 or
    (1000ul * 1000ul * 1000ul) introduces complications I'd rather avoid.
    It *might* be perfectly safe, but I'm uncomfortable relying on it.
    If nothing else, if the program misbehaves, it's one less thing to
    worry about while tracking down the bug.


    IMHO, improvement that 1e9 brings in readability and in elimination of possibilities of mis-typing is worth all extremely unlikely troubles
    that you mentioned above. YMMV.








    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Michael S@3:633/10 to All on Mon Mar 30 11:23:32 2026
    On Mon, 30 Mar 2026 09:25:39 +0200
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 2026-03-30 01:41, Mike Terry wrote:
    On 29/03/2026 13:30, Janis Papanagnou wrote:
    On 2026-03-28 21:58, Josef M”llers wrote:
    On 27.03.26 17:02, Scott Lurndal wrote:
    =?UTF-8?Q?Josef_M=C3=B6llers?= <josef@invalid.invalid> write
    s:
    On 27.03.26 05:46, Janis Papanagnou wrote:
    Subject: Why is this happening?

    I think because you are doing wrong calculations here:

    ˙ > return ((stop.tv_sec-started.tv_sec) + (stop.tv_nsec-
    started.tv_nsec)) / B;

    You should not subtract the components s/ns separately when
    scaling. Instead build the float stop number and started
    number separately and then subtract.

    I usually subtract the nsec parts and if the result is
    negative, adjust
    the sec and the nsec parts accordingly:

    That's fine if you operate on the integer parts separately. (I'm
    sometimes doing a similar thing if I'm working with the integral
    components of a calendar date, for example.)

    Generally I prefer to use types that fit the element I'm operating
    on. That's why I prefer to express˙ dT = stop_time - start_time
    in the case above as
    ˙˙ (stop_s + F * stop_ns) - (start_s + F * start_ns)˙
    ˙ with F=1e-9
    to easily see the application entities and logic.

    I think that's the clearest expression, and it's an expression
    without conditional. (A habit from the early days of programming
    where conditionals were suboptimal. Nowadays it's meaningless,
    and huge amounts of time wasted at other places; using suboptimal
    algorithms, or over-complicated processes, or just bloat.) The
    expressions in your variant appear to me unnecessary confusing
    with using '1000000000UL', for example. - As said, basically a
    matter of personal preference, despite the rationale of clarity,
    which is also mostly subjective.

    We have a calculation here, which ignoring precision issues is of
    the form

    ˙˙ (A1˙ +˙ A2)˙ -˙ (B1˙ +˙ B2)

    The magnitudes are such that A1,B1 are some order of magnitude
    greater than A2,B2, but the differences A1-B1, A2-B2 are of broadly
    similar magnitude (in the scenario we're considering).˙ If we were
    using a single integral type for everything, or some kind of
    infinite precision real numbers, the order of calculation would not
    matter, but floating point is not like that - the order of
    calculation can give different results, due to the finite precision
    limits.

    In such a situation, it's surely good practice to subtract the
    components of similar magnitude first, then add the results, as
    this avoids unnecessarily dropping the precision of the final
    result.˙ That seems more important than how subjectively clear the expression might look to someone. :)

    So I'd go with the original (A1-B1) + (A2-B2) expression, even if
    someone does some calculation to show that on a particular
    architecture, with the actual float/time types being used, the "logical/clearest expression" ordering ((A1+A2) - (B1+B2)) is /sufficiently/ precise for purposes.

    Mike, I see where you're coming from; from numerical mathematics. In
    cases where you have to accumulate many values of different magnitude
    what you describe is necessary to not lose the values of minor value
    in the final sum, since a large amount of such values may contribute.
    Here we were calculating run-times. A "problem" arises if you cannot represent huge seconds values combined with high resolution nano-sec
    values in one, say, double variable. If one thinks that, say, with
    runtime of minutes or hours the least nanoseconds resolution is (for
    your case) of interest you may do that. (And mind that we're still
    not accumulating many such values!) But usually an IEEE double float
    with 64 bit and ~16 decimal figures should suffice for that purpose.

    No, it isn't.
    IEEE binary64 a.k.a. C double is capable to represent exact nanoseconds
    only up to 104 days. So, for UNIX epoch, it had ran out of nanoseconds precision a year or two before KT had first working system.
    By now, Unix time presented in 'double' would have delta=256nsec.
    With Windows FILETIME epoch (January 1, 1601) it would be 8 times worse.

    OTOH, 64-bit signed integer is sufficient for nsec resolution with Unix
    epoch, but insufficient (by one bit) with Windows FILETIME epoch.


    YMMV.

    No, it is not a matter of mileage. There is a correct way (Mike's and
    DFS's and of just about everybody else's who posted in this thread) and incorrect way - yours.

    For me, having seen a lot of good and bad code, clarity of code
    is an essential software property so I'd not unnecessarily muddy the
    code for a requirement we actually don't seem to have (in this case).

    Janis




    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Janis Papanagnou@3:633/10 to All on Mon Mar 30 11:16:04 2026
    On 2026-03-30 10:23, Michael S wrote:
    On Mon, 30 Mar 2026 09:25:39 +0200
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 2026-03-30 01:41, Mike Terry wrote:
    On 29/03/2026 13:30, Janis Papanagnou wrote:
    On 2026-03-28 21:58, Josef M”llers wrote:
    On 27.03.26 17:02, Scott Lurndal wrote:
    =?UTF-8?Q?Josef_M=C3=B6llers?= <josef@invalid.invalid> writes:
    On 27.03.26 05:46, Janis Papanagnou wrote:
    Subject: Why is this happening?

    I think because you are doing wrong calculations here:

    ˙ > return ((stop.tv_sec-started.tv_sec) + (stop.tv_nsec-
    started.tv_nsec)) / B;

    You should not subtract the components s/ns separately when
    scaling. Instead build the float stop number and started
    number separately and then subtract.

    I usually subtract the nsec parts and if the result is
    negative, adjust
    the sec and the nsec parts accordingly:

    That's fine if you operate on the integer parts separately. (I'm
    sometimes doing a similar thing if I'm working with the integral
    components of a calendar date, for example.)

    Generally I prefer to use types that fit the element I'm operating
    on. That's why I prefer to express˙ dT = stop_time - start_time
    in the case above as
    ˙˙ (stop_s + F * stop_ns) - (start_s + F * start_ns)˙˙ with F=1e-9
    to easily see the application entities and logic.

    I think that's the clearest expression, and it's an expression
    without conditional. (A habit from the early days of programming
    where conditionals were suboptimal. Nowadays it's meaningless,
    and huge amounts of time wasted at other places; using suboptimal
    algorithms, or over-complicated processes, or just bloat.) The
    expressions in your variant appear to me unnecessary confusing
    with using '1000000000UL', for example. - As said, basically a
    matter of personal preference, despite the rationale of clarity,
    which is also mostly subjective.

    We have a calculation here, which ignoring precision issues is of
    the form

    ˙˙ (A1˙ +˙ A2)˙ -˙ (B1˙ +˙ B2)

    The magnitudes are such that A1,B1 are some order of magnitude
    greater than A2,B2, but the differences A1-B1, A2-B2 are of broadly
    similar magnitude (in the scenario we're considering).˙ If we were
    using a single integral type for everything, or some kind of
    infinite precision real numbers, the order of calculation would not
    matter, but floating point is not like that - the order of
    calculation can give different results, due to the finite precision
    limits.

    In such a situation, it's surely good practice to subtract the
    components of similar magnitude first, then add the results, as
    this avoids unnecessarily dropping the precision of the final
    result.˙ That seems more important than how subjectively clear the
    expression might look to someone. :)

    So I'd go with the original (A1-B1) + (A2-B2) expression, even if
    someone does some calculation to show that on a particular
    architecture, with the actual float/time types being used, the
    "logical/clearest expression" ordering ((A1+A2) - (B1+B2)) is
    /sufficiently/ precise for purposes.

    Mike, I see where you're coming from; from numerical mathematics. In
    cases where you have to accumulate many values of different magnitude
    what you describe is necessary to not lose the values of minor value
    in the final sum, since a large amount of such values may contribute.
    Here we were calculating run-times. A "problem" arises if you cannot
    represent huge seconds values combined with high resolution nano-sec
    values in one, say, double variable. If one thinks that, say, with
    runtime of minutes or hours the least nanoseconds resolution is (for
    your case) of interest you may do that. (And mind that we're still
    not accumulating many such values!) But usually an IEEE double float
    with 64 bit and ~16 decimal figures should suffice for that purpose.

    No, it isn't.
    IEEE binary64 a.k.a. C double is capable to represent exact nanoseconds
    only up to 104 days. [...]

    So it's even better than my conservative "minutes or hours". Thanks
    for making my point.

    Besides that you seem to have completely missed what I actually said.

    With your figures; do you need in runtime measurements of 104 days a
    resolution of nanoseconds? - If so[*], as I already said above, you
    may do that (i.e. using other methods than using a IEEE double float).
    In my experience for such purposes there's other requirements than
    64 bit of resolution. (In yours it may be different; "YMMV" as I say.)

    [*] And if that resolution is supported by the respective OSes in the
    first place of course.

    YMMV.

    No, it is not a matter of mileage.

    If you have other requirements that's (in my understanding) an issue
    of mileages. (My English may not be good enough, though, so I may
    misunderstand what mileage means, or what you might mean by that.)

    There is a correct way (Mike's and
    DFS's and of just about everybody else's who posted in this thread) and incorrect way - yours.

    (You presented many times already that you have a personal problem.
    You don't need to constantly expose your mindset. Please calm down.
    Myself I'm not interested in personal attacks.)

    If, OTOH, I missed something essential you said (that considers what
    I said, of course), you're welcome to clarify that without constantly
    playing your offending game.

    Janis


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Michael S@3:633/10 to All on Mon Mar 30 13:06:32 2026
    On Mon, 30 Mar 2026 11:16:04 +0200
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 2026-03-30 10:23, Michael S wrote:
    On Mon, 30 Mar 2026 09:25:39 +0200
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 2026-03-30 01:41, Mike Terry wrote:
    On 29/03/2026 13:30, Janis Papanagnou wrote:
    On 2026-03-28 21:58, Josef M”llers wrote:
    On 27.03.26 17:02, Scott Lurndal wrote:
    =?UTF-8?Q?Josef_M=C3=B6llers?= <josef@invalid.invalid> wri
    tes:

    On 27.03.26 05:46, Janis Papanagnou wrote:
    Subject: Why is this happening?

    I think because you are doing wrong calculations here:

    ˙ > return ((stop.tv_sec-started.tv_sec) + (stop.tv_nsec-
    started.tv_nsec)) / B;

    You should not subtract the components s/ns separately when
    scaling. Instead build the float stop number and started
    number separately and then subtract.

    I usually subtract the nsec parts and if the result is
    negative, adjust
    the sec and the nsec parts accordingly:

    That's fine if you operate on the integer parts separately. (I'm
    sometimes doing a similar thing if I'm working with the integral
    components of a calendar date, for example.)

    Generally I prefer to use types that fit the element I'm
    operating on. That's why I prefer to express˙ dT = stop_time -
    start_time in the case above as
    ˙˙ (stop_s + F * stop_ns) - (start_s + F * start_ns)?
    ?˙ with
    F=1e-9 to easily see the application entities and logic.

    I think that's the clearest expression, and it's an expression
    without conditional. (A habit from the early days of programming
    where conditionals were suboptimal. Nowadays it's meaningless,
    and huge amounts of time wasted at other places; using suboptimal
    algorithms, or over-complicated processes, or just bloat.) The
    expressions in your variant appear to me unnecessary confusing
    with using '1000000000UL', for example. - As said, basically a
    matter of personal preference, despite the rationale of clarity,
    which is also mostly subjective.

    We have a calculation here, which ignoring precision issues is of
    the form

    ˙˙ (A1˙ +˙ A2)˙ -˙ (B1˙ +˙
    B2)

    The magnitudes are such that A1,B1 are some order of magnitude
    greater than A2,B2, but the differences A1-B1, A2-B2 are of
    broadly similar magnitude (in the scenario we're considering).
    If we were using a single integral type for everything, or some
    kind of infinite precision real numbers, the order of calculation
    would not matter, but floating point is not like that - the order
    of calculation can give different results, due to the finite
    precision limits.

    In such a situation, it's surely good practice to subtract the
    components of similar magnitude first, then add the results, as
    this avoids unnecessarily dropping the precision of the final
    result.˙ That seems more important than how subjectively clear t
    he
    expression might look to someone. :)

    So I'd go with the original (A1-B1) + (A2-B2) expression, even if
    someone does some calculation to show that on a particular
    architecture, with the actual float/time types being used, the
    "logical/clearest expression" ordering ((A1+A2) - (B1+B2)) is
    /sufficiently/ precise for purposes.

    Mike, I see where you're coming from; from numerical mathematics.
    In cases where you have to accumulate many values of different
    magnitude what you describe is necessary to not lose the values of
    minor value in the final sum, since a large amount of such values
    may contribute. Here we were calculating run-times. A "problem"
    arises if you cannot represent huge seconds values combined with
    high resolution nano-sec values in one, say, double variable. If
    one thinks that, say, with runtime of minutes or hours the least
    nanoseconds resolution is (for your case) of interest you may do
    that. (And mind that we're still not accumulating many such
    values!) But usually an IEEE double float with 64 bit and ~16
    decimal figures should suffice for that purpose.

    No, it isn't.
    IEEE binary64 a.k.a. C double is capable to represent exact
    nanoseconds only up to 104 days. [...]

    So it's even better than my conservative "minutes or hours". Thanks
    for making my point.

    Besides that you seem to have completely missed what I actually said.

    With your figures; do you need in runtime measurements of 104 days a resolution of nanoseconds? - If so[*], as I already said above, you
    may do that (i.e. using other methods than using a IEEE double float).
    In my experience for such purposes there's other requirements than
    64 bit of resolution. (In yours it may be different; "YMMV" as I say.)

    [*] And if that resolution is supported by the respective OSes in the
    first place of course.

    YMMV.

    No, it is not a matter of mileage.

    If you have other requirements that's (in my understanding) an issue
    of mileages. (My English may not be good enough, though, so I may misunderstand what mileage means, or what you might mean by that.)


    "Other requirements" are original requirements. Both A1 and B1 taken
    from tv_sec field of 'struct timespec' that is returned by either timespec_get() or clock_gettime(). The base for those values, IIRC, is
    not specified by C Standard, but on majority of "hosted" C
    environments, even non-Unix, it follows Unix tradition (and POSIX
    requirements ?) of being seconds since start of Unix Epoch.

    There is a correct way (Mike's and
    DFS's and of just about everybody else's who posted in this thread)
    and incorrect way - yours.

    (You presented many times already that you have a personal problem.
    You don't need to constantly expose your mindset. Please calm down.
    Myself I'm not interested in personal attacks.)


    I have problems with people that express full confidence while
    discussing issues they have only very basic ideas about.
    You are not the only one like that in c.l.c but in your case I have a
    hope that conditions are curable. The latter is the only part that you
    can take as personal.

    If, OTOH, I missed something essential you said (that considers what
    I said, of course), you're welcome to clarify that without constantly
    playing your offending game.

    Janis







    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From James Kuyper@3:633/10 to All on Mon Mar 30 20:37:06 2026
    On 2026-03-29 16:54, Keith Thompson wrote:
    ...
    context that doesn't need floating-point. I'm not sure whether
    (unsigned long)1e9 is actually guaranteed to yield 1000000000 rather
    than 999999999. Maybe it is, but I don't want to waste brain cells
    proving it.

    I'll waste my brain cells.

    "When a finite value of decimal floating type is converted to an integer
    type other than bool, the fractional part is discarded (i.e. the value
    is truncated toward zero)." (6.3.2.4p2)

    "For decimal floating literals ... the result is either the nearest representable value, or the larger or smaller representable value
    immediately adjacent to the nearest representable value, chosen in an implementation-defined manner." (6.4.5.3p4)

    This allows for 1e9 to have a value of exactly 1000000000.0, or slightly higher, which converts to unsigned long as 1000000000, or a value
    slightly less than 1000000000.0, which will convert to 999999999.

    So you were right - don't use floating point to do what integer types
    are sufficient to do.


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Michael S@3:633/10 to All on Tue Mar 31 11:48:30 2026
    On Mon, 30 Mar 2026 20:37:06 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wrote:

    On 2026-03-29 16:54, Keith Thompson wrote:
    ...
    context that doesn't need floating-point. I'm not sure whether
    (unsigned long)1e9 is actually guaranteed to yield 1000000000 rather
    than 999999999. Maybe it is, but I don't want to waste brain cells
    proving it.

    I'll waste my brain cells.

    "When a finite value of decimal floating type is converted to an
    integer type other than bool, the fractional part is discarded (i.e.
    the value is truncated toward zero)." (6.3.2.4p2)

    "For decimal floating literals ... the result is either the nearest representable value, or the larger or smaller representable value
    immediately adjacent to the nearest representable value, chosen in an implementation-defined manner." (6.4.5.3p4)

    This allows for 1e9 to have a value of exactly 1000000000.0, or
    slightly higher, which converts to unsigned long as 1000000000, or a
    value slightly less than 1000000000.0, which will convert to
    999999999.


    Not when compiler declares itself compliant with IEEE-754 (or IEC
    559). By 754, if value is representable exactly then it shall be
    chosen, unconditionally. No "adjacent" allowed.

    So you were right - don't use floating point to do what integer types
    are sufficient to do.


    You can do what you feel right. And I would do what I feel right.
    And I am going to continue to suggest what I think is right to other
    people that, like me, care very little about what weird things are
    permitted to implementer according to C Standard as long as all
    implementations that they are likely to encounter in practice provide
    much stronger guarantees.







    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Tue Mar 31 16:20:42 2026
    On 29/03/2026 19:37, Tim Rentsch wrote:
    Richard Harnden <richard.nospam@gmail.invalid> writes:

    On 29/03/2026 10:33, David Brown wrote:

    On 28/03/2026 17:58, Richard Harnden wrote:

    On 28/03/2026 15:35, David Brown wrote:

    Well, underscore basically counts as a letter, so it's a valid
    identifier just like "x1234" would be. Sometimes people use
    identifiers like that for specific purposes, like macro
    parameters.

    Isn't _UPPERCASE and __anything reserved for the implementation?

    Yes.

    And identifiers with _lowercase have implicit internal linkage (when
    they would otherwise have had implicit external linkage). That's
    why I wrote "underscore /basically/ counts as a letter" - to save
    mentioning all the details.

    I didn't know that, thanks.

    Don't believe everything you read. Of course, as far as the C
    standard is concerned, defining a reserved name is undefined
    behavior, but actual compilers have different behavior than what
    is suggested above.

    So, at file scope, these are equivalent ... ?
    static int foo;
    int _foo;

    If you try with gcc or clang (which I did), I expect you will
    find that _foo is an ordinary global symbol. It does not have
    "implicit internal linkage". It is treated just like any other
    external definition.


    Thanks for the correction. Identifiers starting with an underscore are "reserved for file scope". I believe that means non-static file-scope
    "int _foo;" is therefore UB, but there is no implied "static".



    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Tue Mar 31 16:26:06 2026
    On 29/03/2026 22:57, Keith Thompson wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 28/03/2026 17:58, Richard Harnden wrote:
    On 28/03/2026 15:35, David Brown wrote:
    Well, underscore basically counts as a letter, so it's a valid
    identifier just like "x1234" would be.˙ Sometimes people use
    identifiers like that for specific purposes, like macro parameters.
    Isn't _UPPERCASE and __anything reserved for the implementation?

    Yes.

    And identifiers with _lowercase have implicit internal linkage (when
    they would otherwise have had implicit external linkage). That's why
    I wrote "underscore /basically/ counts as a letter" - to save
    mentioning all the details.

    I don't believe that's correct. The language defines rules about
    which identifiers are reserved depending on how they're spelled,
    but I've never seen a rule that says the linkage of an identifier
    is affected by its spelling. (A compiler could take advantage of
    undefined behavior to do something weird, but I believe and hope
    that no compilers actually do so.)


    I was incorrect in what I wrote - I looked it up again after reading
    Tim's post. Identifiers starting with an underscore are reserved for file-scope, but do not automatically get internal linkage.

    (I have seen code where it appears the programmer assumed functions with
    names starting with an underscore were internal linkage. I did not like
    the way it was written, but I had assumed it was correct. Most likely,
    the code worked fine simply because there were no other uses of the same identifier in other TUs.)


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From James Kuyper@3:633/10 to All on Tue Mar 31 10:51:43 2026
    On 2026-03-31 04:48, Michael S wrote:
    On Mon, 30 Mar 2026 20:37:06 -0400
    James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    ...
    "When a finite value of decimal floating type is converted to an
    integer type other than bool, the fractional part is discarded (i.e.
    the value is truncated toward zero)." (6.3.2.4p2)

    "For decimal floating literals ... the result is either the nearest
    representable value, or the larger or smaller representable value
    immediately adjacent to the nearest representable value, chosen in an
    implementation-defined manner." (6.4.5.3p4)

    This allows for 1e9 to have a value of exactly 1000000000.0, or
    slightly higher, which converts to unsigned long as 1000000000, or a
    value slightly less than 1000000000.0, which will convert to
    999999999.


    Not when compiler declares itself compliant with IEEE-754 (or IEC
    559). By 754, if value is representable exactly then it shall be
    chosen, unconditionally. No "adjacent" allowed.

    I was talking about what the C standard requires. While the standard
    allows your code to determine whether or not it is being translated by
    an implementation which supports IEEE/IEC 60559, it doesn't mandate such support.

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Richard Harnden@3:633/10 to All on Tue Mar 31 17:19:42 2026
    On 31/03/2026 15:20, David Brown wrote:
    On 29/03/2026 19:37, Tim Rentsch wrote:
    Richard Harnden <richard.nospam@gmail.invalid> writes:

    On 29/03/2026 10:33, David Brown wrote:

    On 28/03/2026 17:58, Richard Harnden wrote:

    On 28/03/2026 15:35, David Brown wrote:

    Well, underscore basically counts as a letter, so it's a valid
    identifier just like "x1234" would be.˙ Sometimes people use
    identifiers like that for specific purposes, like macro
    parameters.

    Isn't _UPPERCASE and __anything reserved for the implementation?

    Yes.

    And identifiers with _lowercase have implicit internal linkage (when
    they would otherwise have had implicit external linkage).˙ That's
    why I wrote "underscore /basically/ counts as a letter" - to save
    mentioning all the details.

    I didn't know that, thanks.

    Don't believe everything you read.˙ Of course, as far as the C
    standard is concerned, defining a reserved name is undefined
    behavior, but actual compilers have different behavior than what
    is suggested above.

    So, at file scope, these are equivalent ... ?
    ˙˙˙ static int foo;
    ˙˙˙ int _foo;

    If you try with gcc or clang (which I did), I expect you will
    find that _foo is an ordinary global symbol.˙ It does not have
    "implicit internal linkage".˙ It is treated just like any other
    external definition.

    b
    Thanks for the correction.˙ Identifiers starting with an underscore are "reserved for file scope".˙ I believe that means non-static file-scope
    "int _foo;" is therefore UB, but there is no implied "static".



    Thanks. I think I will simply avoid avoid any variable names prefixed
    with an '_'.


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From candycanearter07@3:633/10 to All on Tue Mar 31 19:00:03 2026
    James Kuyper <jameskuyper@alumni.caltech.edu> wrote at 00:37 this Tuesday (GMT):
    On 2026-03-29 16:54, Keith Thompson wrote:
    ...
    context that doesn't need floating-point. I'm not sure whether
    (unsigned long)1e9 is actually guaranteed to yield 1000000000 rather
    than 999999999. Maybe it is, but I don't want to waste brain cells
    proving it.

    I'll waste my brain cells.

    "When a finite value of decimal floating type is converted to an integer
    type other than bool, the fractional part is discarded (i.e. the value
    is truncated toward zero)." (6.3.2.4p2)

    "For decimal floating literals ... the result is either the nearest representable value, or the larger or smaller representable value
    immediately adjacent to the nearest representable value, chosen in an implementation-defined manner." (6.4.5.3p4)

    This allows for 1e9 to have a value of exactly 1000000000.0, or slightly higher, which converts to unsigned long as 1000000000, or a value
    slightly less than 1000000000.0, which will convert to 999999999.

    So you were right - don't use floating point to do what integer types
    are sufficient to do.


    Floats should not be used for any kinda comparisons besides basic
    greater than/less than checks or flooring it beforehand, its just too unreliable.

    also languages that make no distinguishment are very frustrating
    sometimes
    --
    user <candycane> is generated from /dev/urandom

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Tristan Wibberley@3:633/10 to All on Fri Apr 3 02:41:27 2026
    On 28/03/2026 01:46, Lawrence D?Oliveiro wrote:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M”llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    #define NUMg(a,...) a
    #define NUMf(a,...) NUMg(a##__VA_ARGS__)
    #define NUMe(a,...) NUMf(a##__VA_ARGS__)
    #define NUMd(a,...) NUMe(a##__VA_ARGS__)
    #define NUMc(a,...) NUMd(a##__VA_ARGS__)
    #define NUMb(a,...) NUMc(a##__VA_ARGS__)
    #define NUMa(a,...) NUMb(a##__VA_ARGS__)
    #define NUM9(a,...) NUMa(a##__VA_ARGS__)
    #define NUM8(a,...) NUM9(a##__VA_ARGS__)
    #define NUM7(a,...) NUM8(a##__VA_ARGS__)
    #define NUM6(a,...) NUM7(a##__VA_ARGS__)
    #define NUM5(a,...) NUM6(a##__VA_ARGS__)
    #define NUM4(a,...) NUM5(a##__VA_ARGS__)
    #define NUM3(a,...) NUM4(a##__VA_ARGS__)
    #define NUM2(a,...) NUM3(a##__VA_ARGS__)
    #define NUM1(a,...) NUM2(a##__VA_ARGS__)
    #define NUM(a,...) NUM1(a##__VA_ARGS__)

    NUM(1,000,000,UL)


    --
    Tristan Wibberley

    The message body is Copyright (C) 2026 Tristan Wibberley except
    citations and quotations noted. All Rights Reserved except that you may,
    of course, cite it academically giving credit to me, distribute it
    verbatim as part of a usenet system or its archives, and use it to
    promote my greatness and general superiority without misrepresentation
    of my opinions other than my opinion of my greatness and general
    superiority which you _may_ misrepresent. You definitely MAY NOT train
    any production AI system with it but you may train experimental AI that
    will only be used for evaluation of the AI methods it implements.


    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Tim Rentsch@3:633/10 to All on Mon Apr 6 12:11:54 2026
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    scott@slp53.sl.home (Scott Lurndal) writes:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Lawrence D <<E2>> ??Oliveiro <ldo@nz.invalid> writes:

    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M@C3{B6}llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator, copied
    from C++:

    diffns += 1'000'000'000UL;

    Or diffns += 1000ul * 1000ul * 1000ul;

    or diffns += 1 * NS_PER_SEC;

    with
    #define NS_PER_SEC ((1000ul * 1000ul * 1000ul))

    (I would have preferred underscores, but that would have conflicted
    with C++'s user-defined literals.)

    Likewise, I'd prefer the underscore.

    Ditto. And there is no reason C could have allowed both,
    and C++ be damned.

    (I think you omitted a "not".)

    Yes, as I explained in a followup to myself.

    Using apostrophes is IMHO far better than either allowing two
    arbitrarily distinct syntaxes or a gratuitous incompatibility
    with C++.

    One, it is not an incompatibility. It's an upward compatible
    extension.

    Two, it's not gratuitous. The extension is proposed because it
    provides a positive value, and I'm not the only one who thinks
    so.

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Mon Apr 6 14:20:26 2026
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence D <<E2>> ??Oliveiro <ldo@nz.invalid> writes:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M@C3{B6}llers wrote:
    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator, copied >>>>> from C++:

    diffns += 1'000'000'000UL;

    Or diffns += 1000ul * 1000ul * 1000ul;

    or diffns += 1 * NS_PER_SEC;

    with
    #define NS_PER_SEC ((1000ul * 1000ul * 1000ul))

    (I would have preferred underscores, but that would have conflicted
    with C++'s user-defined literals.)

    Likewise, I'd prefer the underscore.

    Ditto. And there is no reason C could have allowed both,
    and C++ be damned.

    (I think you omitted a "not".)

    Yes, as I explained in a followup to myself.

    Using apostrophes is IMHO far better than either allowing two
    arbitrarily distinct syntaxes or a gratuitous incompatibility
    with C++.

    One, it is not an incompatibility. It's an upward compatible
    extension.

    Your proposal, I think, is for C to permit both apostrophes and
    underscores as digit separators. I suppose that's not strictly an "incompatibility", but it would mean that any code intended to be
    compiled as either C or C++ cannot use underscores.

    Your "C++ be damned" attitude is not shared by either language
    committee (fortunately, IMHO).

    Two, it's not gratuitous. The extension is proposed because it
    provides a positive value, and I'm not the only one who thinks
    so.

    I disagree. I've already said that I would have preferred
    underscores over apostrophes, but both languages now use apostrophes.
    If C allowed both, there would be no firm basis for deciding which
    to use. It would make the language slightly more complicated,
    with no real benefit than I can see. The only thing I can think of
    that might be a "positive value" is that *some* programmers would
    be able to use a symbol that they think looks better.

    It would be similar to allowing programmers to use "begin" and "end"
    rather than "{" and "}". I'm sure some programmers would like that,
    but the result would be a mess.

    What positive value do you think permitting underscores would add?

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Michael S@3:633/10 to All on Tue Apr 7 02:05:58 2026
    On Mon, 06 Apr 2026 14:20:26 -0700
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence D <<E2>> ??Oliveiro <ldo@nz.invalid> writes:
    On Fri, 27 Mar 2026 10:15:23 +0100, Josef M@C3{B6}llers wrote:

    diffns += 1000000000UL;

    Can you write

    diffns += 1_000_000_000UL;

    yet?

    Not in C. C23 introduces the apostrophe as a digit separator,
    copied from C++:

    diffns += 1'000'000'000UL;

    Or diffns += 1000ul * 1000ul * 1000ul;

    or diffns += 1 * NS_PER_SEC;

    with
    #define NS_PER_SEC ((1000ul * 1000ul * 1000ul))

    (I would have preferred underscores, but that would have
    conflicted with C++'s user-defined literals.)

    Likewise, I'd prefer the underscore.

    Ditto. And there is no reason C could have allowed both,
    and C++ be damned.

    (I think you omitted a "not".)

    Yes, as I explained in a followup to myself.

    Using apostrophes is IMHO far better than either allowing two
    arbitrarily distinct syntaxes or a gratuitous incompatibility
    with C++.

    One, it is not an incompatibility. It's an upward compatible
    extension.

    Your proposal, I think, is for C to permit both apostrophes and
    underscores as digit separators. I suppose that's not strictly an "incompatibility", but it would mean that any code intended to be
    compiled as either C or C++ cannot use underscores.

    Your "C++ be damned" attitude is not shared by either language
    committee (fortunately, IMHO).


    For C11 and C17 it was true.
    But C23 has at least two new (or old new) incompatibilities with C++:
    - VMT are again mandatory, like in C99
    - _BitInt(N)
    It sounds to me as a change of the attitude. Or may be a return to
    pre-C11 attitude.

    Two, it's not gratuitous. The extension is proposed because it
    provides a positive value, and I'm not the only one who thinks
    so.

    I disagree. I've already said that I would have preferred
    underscores over apostrophes, but both languages now use apostrophes.
    If C allowed both, there would be no firm basis for deciding which
    to use. It would make the language slightly more complicated,
    with no real benefit than I can see. The only thing I can think of
    that might be a "positive value" is that *some* programmers would
    be able to use a symbol that they think looks better.

    It would be similar to allowing programmers to use "begin" and "end"
    rather than "{" and "}". I'm sure some programmers would like that,
    but the result would be a mess.

    What positive value do you think permitting underscores would add?




    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Mon Apr 6 17:42:33 2026
    Michael S <already5chosen@yahoo.com> writes:
    On Mon, 06 Apr 2026 14:20:26 -0700
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    [...]
    Your "C++ be damned" attitude is not shared by either language
    committee (fortunately, IMHO).

    For C11 and C17 it was true.
    But C23 has at least two new (or old new) incompatibilities with C++:
    - VMT are again mandatory, like in C99
    - _BitInt(N)
    It sounds to me as a change of the attitude. Or may be a return to
    pre-C11 attitude.

    It's always been true that C has some features that C++ doesn't.
    In some cases, it's because some features are better implemented
    in C++ as container classes, while C needs them to be implemented
    in the core language. Variably modified types are a good example;
    for most cases where I'd use one in C, I'd probably use std::vector
    in C++. Complex types are another example.

    There is a proposal to add _BitInt to a new edition of C++: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3666r2.html

    That hardly indicates a "C++ be damned" attitude. The two committees
    still coordinate fairly closely, and try to keep the two languages as compatible as reasonably possible.

    C23 uses apostrophes as digit separators because C++ does so.
    I don't know why Tim thinks requiring support for both apostrophes
    and underscores would be an improvement.

    [...]

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.13
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)