return ((stop.tv_sec-started.tv_sec) +(stop.tv_nsec-started.tv_nsec)) / B;
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
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
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
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.
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:
diffns += 1000000000UL;
On Fri, 27 Mar 2026 10:15:23 +0100, Josef Mllers wrote:
diffns += 1000000000UL;
Can you write
diffns += 1_000_000_000UL;
yet?
Lawrence D?Oliveiro <ldo@nz.invalid> writes:
On Fri, 27 Mar 2026 10:15:23 +0100, Josef Mllers 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.)
[...]
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 Mllers 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?
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 Mllers 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.)
Lawrence D?Oliveiro <ldo@nz.invalid> writes:
On Fri, 27 Mar 2026 10:15:23 +0100, Josef Mllers 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.)
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 Mllers 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.)
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 Mllers 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.
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.
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.
=?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.
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?
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.
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.
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.
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?
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".
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.
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;
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?
On 2026-03-28 21:58, Josef Mllers 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.
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.
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?
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 ?
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 validIsn't _UPPERCASE and __anything reserved for the implementation?
identifier just like "x1234" would be.˙ Sometimes people use
identifiers like that for specific purposes, like macro parameters.
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.
Now, lets ponder on *_t?
struct foo_t ?
intrude into POSIX?
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.
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.
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.
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.
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.
"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.
On 29/03/2026 13:30, Janis Papanagnou wrote:
On 2026-03-28 21:58, Josef Mllers wrote:We have a calculation here, which ignoring precision issues is of the form
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.
˙˙ (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.
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.
On 2026-03-30 01:41, Mike Terry wrote:s:
On 29/03/2026 13:30, Janis Papanagnou wrote:
On 2026-03-28 21:58, Josef Mllers wrote:
On 27.03.26 17:02, Scott Lurndal wrote:
=?UTF-8?Q?Josef_M=C3=B6llers?= <josef@invalid.invalid> write
˙ with F=1e-9On 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)˙
to easily see the application entities and logic.We have a calculation here, which ignoring precision issues is of
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.
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
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 Mllers wrote:We have a calculation here, which ignoring precision issues is of
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.
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. [...]
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.
On 2026-03-30 10:23, Michael S wrote:tes:
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 Mllers wrote:
On 27.03.26 17:02, Scott Lurndal wrote:
=?UTF-8?Q?Josef_M=C3=B6llers?= <josef@invalid.invalid> wri
?˙ with
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)?
B2)F=1e-9 to easily see the application entities and logic.We have a calculation here, which ignoring precision issues is of
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.
the form
˙˙ (A1˙ +˙ A2)˙ -˙ (B1˙ +˙
he
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
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
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.
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.
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.
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 validIsn't _UPPERCASE and __anything reserved for the implementation?
identifier just like "x1234" would be.˙ Sometimes people use
identifiers like that for specific purposes, like macro parameters.
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.)
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.
On 29/03/2026 19:37, Tim Rentsch wrote:
Richard Harnden <richard.nospam@gmail.invalid> writes:b
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".
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.
On Fri, 27 Mar 2026 10:15:23 +0100, Josef Mllers wrote:
diffns += 1000000000UL;
Can you write
diffns += 1_000_000_000UL;
yet?
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 <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.
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?
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.
| Sysop: | Tetrazocine |
|---|---|
| Location: | Melbourne, VIC, Australia |
| Users: | 14 |
| Nodes: | 8 (0 / 8) |
| Uptime: | 94:03:35 |
| Calls: | 211 |
| Files: | 21,502 |
| Messages: | 82,381 |