Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CHAR_BIT is not eight

574 views
Skip to first unread message

Frederick Virchanza Gotham

unread,
Oct 12, 2022, 6:57:37 PM10/12/22
to
Since I started programming in C/C++ back in the early 2000's, I never encountered a compiler with CHAR_BIT anything other than 8.

Well just now in the past 15 minutes, I was trying to get the code for the 'base58' algorithm to compile for the Texas Instruments F2809 microcontroller using the 'cl2000' compiler.

At first I was puzzled as to why 'sizeof(long)' was coming back as 2. Of course my first assumption here was that 'long' was 16-Bit (even though the Standard says that a 'long' must be at least 32-Bit). So I figured that this compiler was just non-standard-compliant on a few issues.

After a little messing around, I realised that CHAR_BIT is 16.

I looked through the compiler manual and found this paragraph:

"By ANSI/ISO C definition, the sizeof operator yields the number of bytes required to store an object. ANSI/ISO further stipulates that when sizeof is applied to char, the result is 1. Since the TMS320C28x char is 16 bits (to make it separately addressable), a byte is also 16 bits. This yields results you may not expect; for example, size of (int) = = 1 (not 2). TMS320C28x bytes and words are equivalent (16 bits). To access data in increments of 8 bits, use the __byte() and __mov_byte() intrinsics described in Section 7.6"

So there you go: There are C++ compilers in use today in the year 2022 with CHAR_BIT something other than 8.

Chris M. Thomasson

unread,
Oct 12, 2022, 7:02:09 PM10/12/22
to
At least is should not be less than eight?

Keith Thompson

unread,
Oct 12, 2022, 8:16:54 PM10/12/22
to
Apparently the TMS320C28x is a DSP (Digital Signal Processor). I've
heard that it's common for CHAR_BIT to be 16 or 32 in implementations
for DSPs.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

Juha Nieminen

unread,
Oct 13, 2022, 4:03:38 AM10/13/22
to
Frederick Virchanza Gotham <cauldwel...@gmail.com> wrote:
> So there you go: There are C++ compilers in use today in the year 2022 with CHAR_BIT something other than 8.

The vast, *vast* majority of C and C++ programmers assume that 'char' is
always 8-bit, and sometimes write code making that assumption. It's
*extremely* rare to see any code out there that uses CHAR_BIT at all,
but it's quite common to see code that assumes that it's 8. Most C and
C++ programmers just assume that it's a de-facto universal standard,
and that the actual C and C++ standards are just antiquated in this
regard, by keeping "backwards compatibility" with some more exotic
CPUs from the 1970's that have been completely obsolete for decades.

I suppose there's a good reason why the language standards don't assume
that 'char' is 8 bits, after all.

Mut...@dastardlyhq.com

unread,
Oct 13, 2022, 4:08:54 AM10/13/22
to
A number of current Texas Instruments DSPs have 16 bit chars.

Personally I always use int8_t or uint8_t if I'm writing portable code just
to be 100% sure.

Frederick Virchanza Gotham

unread,
Oct 13, 2022, 5:06:37 AM10/13/22
to
On Thursday, October 13, 2022, Juha Nieminen wrote:
> The vast, *vast* majority of C and C++ programmers assume that 'char' is
> always 8-bit, and sometimes write code making that assumption. It's
> *extremely* rare to see any code out there that uses CHAR_BIT at all,
> but it's quite common to see code that assumes that it's 8. Most C and
> C++ programmers just assume that it's a de-facto universal standard,
> and that the actual C and C++ standards are just antiquated in this
> regard, by keeping "backwards compatibility" with some more exotic
> CPUs from the 1970's that have been completely obsolete for decades.
>
> I suppose there's a good reason why the language standards don't assume
> that 'char' is 8 bits, after all.


I totally agree. I've been using C++ compilers for about 20 years now, and yesterday was the first time I encountered CHAR_BIT != 8. Lots of my code uses "char unsigned" and "uint8_t" interchangeably.


On Thursday, October 13, 2022, Mut...@... wrote:
> A number of current Texas Instruments DSPs have 16 bit chars.
>
> Personally I always use int8_t or uint8_t if I'm writing portable
> code just to be 100% sure.

I'm writing a 'universal header file' today that will be used in a program on:
1) x86_64 desktop PC
2) microcontroller Texas Instruments F2809 (with 16-Bit bytes)
3) microcontroller Arduino sam3x8e

If I include "cstdint", then it doesn't have "uint8_t" on the Texas Instruments compiler. So I'm using "uint_least8_t" in the code.

Bo Persson

unread,
Oct 13, 2022, 5:10:22 AM10/13/22
to
Often you *can* make the assumption that you have 8-bit chars, and
really not care about any other options.

A lot of code will not run on a signal processor anyway, because it uses
resources that are not available there, like a database or a desktop
user interface.

David Brown

unread,
Oct 13, 2022, 5:38:37 AM10/13/22
to
Yes, that's correct. The TMS320 family are widely used in industrial
electronics and high reliability or rough environment systems. They
have 16-bit char.

Most DSPs these days are very specialised devices, only programmed by a
very few people and with virtually no overlap with "normal" programming.
It's much easier to use a "normal" processor with SIMD and vector
instructions to do the same job that previously needed a DSP for speed.
But a DSP might have instructions that can handle multiple memory
accesses from different ram banks, multiply-accumulate-saturate
operations, pointer update with circular buffer wrapping or FFT
bit-twiddling, loop counter decrement and checking, all within a single
one-clock instruction. You don't really program these in C (much less
C++) - it's really assembly, wrapped in a a C intrinsic.

However, these are usually "hidden" coprocessors, using
manufacturer-written binary blobs, rather than programmed by "normal"
programmers. So your mobile phone chip might have a bunch of normal ARM
cores and a hidden DSP for software-defined radio that you never access
directly.

There are also some DSP cores with odder CHAR size than 16 or 32,
including soft cores where the size of a "byte" is determined when you
add the core to your ASIC or FPGA. 24-bit used to be very common for
audio and visual systems.

The TMS320 and related devices from Texas Instruments are one of the few
types of DSP that are still used by a wide variety of developers. Just
be careful of TI's development tools - they have a tradition of being a
little loose on standards conformance. A particular common feature of
many of TI's tools is that they don't bother zero-initialising
statically allocated implicitly initialised data (the ".bss" segment).
That one caused me a lot of "fun" on a couple of occasions, once with a
TMS320F28x device and once with a very different kind of microcontroller.

David Brown

unread,
Oct 13, 2022, 5:43:07 AM10/13/22
to
That's one solution, yes.

Another is to avoid 8-bit types entirely, and use uint16_t as your
smallest type. That makes it easier to be sure sizes and structs are
the same size in every case. (This depends on what you need to do in
the header, of course.) Static assertions are your friend to ensure
that everything (such as struct size) is as you expect on all targets.

It is not common to program DSP's like the TMS320 using C++ - usually C
is the language of choice. But maybe TI's C++ compilers have improved
since I last looked (which was a long time ago). It's generally not
hard to make a common header that is suitable for C and C++, for
flexibility.

Juha Nieminen

unread,
Oct 13, 2022, 6:49:33 AM10/13/22
to
OTOH if you are making eg. a library that's supposed to be as
standard-conforming and as portable as possible, you should start
caring about CHAR_BIT, if your library somehow cares about bits,
accesses bits, and cares about the sizes of types in bits.

(Thinking about it, I have myself made some such libraries. I'll have
to go and review them from this perspective, and make sure they don't
make that assumption.)

Juha Nieminen

unread,
Oct 13, 2022, 8:05:38 AM10/13/22
to
Juha Nieminen <nos...@thanks.invalid> wrote:
> (Thinking about it, I have myself made some such libraries. I'll have
> to go and review them from this perspective, and make sure they don't
> make that assumption.)

Interesting question: If you write a library that cares about bit sizes,
and uses CHAR_BIT in order to not assume that 'char' has 8 bits, how would
you write unit tests that check that the library works correctly with
CHAR_BIT sizes other than 8?

Frederick Virchanza Gotham

unread,
Oct 13, 2022, 9:34:12 AM10/13/22
to
You go buy a Texas Instruments development board, upload your machine code, and communicate over RS232 to see if it's working. That's what I'm doing today.

David Brown

unread,
Oct 13, 2022, 9:59:32 AM10/13/22
to
It is very rare that "as portable as possible" is a realistic
specification. It happens, but it is not common. Of course I don't
recommend making assumptions about the target unless they are useful in
some way, but there is no point in going out of your way to make code
portable beyond any realistic targets. So if you need an eight bit
variable, write "uint8_t" - if it turns out that your code gets used in
unexpected places where CHAR_BIT is not 8, then at least there will be a
clear compile-time failure. There's no point in going overboard in
portability if it reduces the readability or efficiency of the code you
are writing.

As someone who has occasionally written code for 16-bit char devices
(and worked alongside others who have used 32-bit char devices), I
actually see it as an advantage that the code I generally write does
/not/ compile on these devices. My code is not tested or checked on
16-bit char targets, and it is unlikely to be the most efficient code
for such targets - if I or someone else wants to use the code on such
systems, I'd rather they were forced to work through the code, checking
it and re-writing as necessary, rather than just assuming it works
because it compiles.

If your code makes use of "char", or "uint8_t", or "uint_least8_t", or
other types that are 8 bit on most targets, then it is likely that the
code is not efficient on a 16-bit char DSP. You are likely to be
wasting space (the first TMS320 device I used had about 300 bytes of ram
in total - you do not waste 16-bit "bytes" to store a single character),
are possibly getting different, unexpected and untested integral
promotions, and could be failing to take advantage of the special
features of the target. And if efficient code is not the goal, such
DSP's are almost certainly not the best devices for the task in the
first place.

Sometimes there is a bit of shared code across such widely separated
architectures - such as the OP's shared header. But most code for a DSP
is written directly for the device.


Ben Bacarisse

unread,
Oct 13, 2022, 10:24:33 AM10/13/22
to
I don't think there's any automatic way[1]. But you can start by
looking for places that directly or indirectly refer to 8 bit
quantities: a literal 8, shifts of 7 or 3 places, constants like 0xff,
256 or 0400 and limits like 0xfe, 255 or 0377. The corresponding
negative quantities should be searched for as well if signed char (or an
assumed signed char) is being used.

And of course you have to check that any uses of the macros CHAR_BIT and
[SU]?CHAR_(MIN|MAX) are appropriate and don't suggest any unwarranted
assumptions about their values.

[1] Unless it's C code where some sort of 'lint' program might be able
to help. I've not seen a lint-type program for C++...

--
Ben.

Mut...@dastardlyhq.com

unread,
Oct 13, 2022, 11:37:18 AM10/13/22
to
On Thu, 13 Oct 2022 11:42:50 +0200
David Brown <david...@hesbynett.no> wrote:
>It is not common to program DSP's like the TMS320 using C++ - usually C
>is the language of choice. But maybe TI's C++ compilers have improved
>since I last looked (which was a long time ago). It's generally not
>hard to make a common header that is suitable for C and C++, for
>flexibility.

IIRC some of the TI chips use 16 bit addressing so 32 bit addressing requires a
lot of faffing around with paging and offsets which makes using pointers very
expensive and that in turn makes C++ features such as virtual functions
slow and even assuming the STL would even fit in memory it would run like a
half dead dog.

David Brown

unread,
Oct 13, 2022, 5:07:11 PM10/13/22
to
Most of these chips don't have more than 64 KB memory (flash and ram) to
address, making that a moot point. But you do get the fun of multiple
address spaces in many DSPs.

There are other TI chips that /do/ have 16-bit pointers and on some
devices have more than 64 KB memory. Some of the MSP430 devices are
like that. Some of them have "solved" this by having 20-bit registers,
which adds to their interest. (The pure 16-bit MSP430 are very
C-friendly, with an architecture similar to the original C DEC targets.)

Yes, paging of any kind is a pain for some kinds of coding that you take
for granted on "big" processors. But for the kinds of systems these
devices target, you almost never want any kind of dynamic memory anyway
- thus you have no problems with the C++ standard library containers
because you'd never use such things (other than std::array).

Mr Flibble

unread,
Oct 13, 2022, 5:30:50 PM10/13/22
to
On Thu, 13 Oct 2022 23:06:51 +0200
Why just std::array? You could use any container with a suitable
allocator.

/Flibble

Juha Nieminen

unread,
Oct 14, 2022, 1:54:49 AM10/14/22
to
David Brown <david...@hesbynett.no> wrote:
> It is very rare that "as portable as possible" is a realistic
> specification. It happens, but it is not common.

"Not common" does not mean "you shouldn't care", when you are writing
a library that could potentially be used in more exotic architectures,
such as the one mentioned in this thread.

For example if you are writing, say, a small library that calculates
hashes or checksums using a particular algorithm. It's not at all
unrealistic that such a library could have uses in these more exotic
microcontrollers (as microcontrollers are often used in embedded
systems that handle data somehow, and might be interested in calculating
things like checksums and hashes). And it is quite likely that such
an algorithm might care about bit sizes.

Paavo Helde

unread,
Oct 14, 2022, 2:17:15 AM10/14/22
to
True, but for really supporting such exotic platforms one would need to
run tests on these platforms (or at least in an emulator) during the
development and potentially also later if anything changes.

Software without tests is just a work of literature.

And testing for such exotic platforms might easily multiply the costs of
the project by a large factor.

That does not mean one should not attempt to write code in a reasonably
generic way, but there are some limits.

Frederick Virchanza Gotham

unread,
Oct 14, 2022, 3:17:44 AM10/14/22
to
On Friday, October 14, 2022 at 6:54:49 AM UTC+1, Juha Nieminen wrote:

> For example if you are writing, say, a small library that calculates
> hashes or checksums using a particular algorithm. It's not at all
> unrealistic that such a library could have uses in these more exotic
> microcontrollers (as microcontrollers are often used in embedded
> systems that handle data somehow, and might be interested in calculating
> things like checksums and hashes). And it is quite likely that such
> an algorithm might care about bit sizes.


I have the code for an encryption algorithm here, which I got off Github. The code is a single C++ header file that's supposed to be fully-portable. I want to take this header file and add it to my own 'universal header file' which will be used on microcontrollers and desktop PC's. I've looked through the encryption header file, and I see that they use "unsigned short" for anything up to 65 thousand, and then "unsigned long" for anything up to 4 billion, so that's fine. There are however a few lines I have to tweak, such as the following:

p[i] = p[i - 1] << 4u;

I need to make that:

p[i] = (p[i-1] << 4u) & 0xF0;

To be honest, discovering a computer-and-compiler-combo with a CHAR_BIT != 8 like this is quite an experience for me. It's like I'm a biologist who's been dealing with carbon-based life forms all his life, and they've flown me in a silicon-based life form from Mars and I have it under my microscope. Twenty years is a long time to have CHAR_BIT invariably equal to 8.

I'm re-writing the encryption code so that it deals in 32-Bit chunks, and I'm using 'uint_least32_t' for that purpose just in case there isn't a 32-Bit type.

David Brown

unread,
Oct 14, 2022, 9:27:31 AM10/14/22
to
Yes, it is always /possible/. But the complications and effort involved
is unlikely to be worth the effort, and you'd still end up with
something taking a massive amount of code space. (With "massive" being
relative to the small code memories of such systems.)

It's not uncommon in my coding to build up a few lists at the startup of
the system - lists of "run" functions or software timers, etc. Modules
might register such callbacks or functions when initialised. In "big
system" C++, you might just use a vector for that - adding your timer
objects to your vector as needed. It's simple and easy in the code.

But in a resource-constraint embedded system, where efficiency of code
space, ram space and run-time is important (though run-time efficiency
is usually less important for startup code), that's not what you would
do. You make your timer class have the required list link pointers in
the class, have each registering function declare their timer object
with static lifetime, and your registration function links them together.

There's no doubt that this takes a bit more effort to write than an
off-the-shelf std::vector. But it is vastly simpler than faffing around
making your own allocator, avoids the use of any kind of dynamic memory
(using neither the standard heap nor a home-made allocation system), and
pulls in a tiny fraction of the amount of library code.

std::array<> is free - it's just a nice wrapper around a plain C-style
array.


David Brown

unread,
Oct 14, 2022, 9:33:52 AM10/14/22
to
On 14/10/2022 09:17, Frederick Virchanza Gotham wrote:
> On Friday, October 14, 2022 at 6:54:49 AM UTC+1, Juha Nieminen wrote:
>
>> For example if you are writing, say, a small library that calculates
>> hashes or checksums using a particular algorithm. It's not at all
>> unrealistic that such a library could have uses in these more exotic
>> microcontrollers (as microcontrollers are often used in embedded
>> systems that handle data somehow, and might be interested in calculating
>> things like checksums and hashes). And it is quite likely that such
>> an algorithm might care about bit sizes.
>
>
> I have the code for an encryption algorithm here, which I got off Github.

You'll want to check that code anyway. There's a lot of excellent code
on Github, but there's also a lot of rubbish or questionable code
masquerading as good code. If reliable encryption is important, you
have to be very careful - remember that testing can only show the
presence of bugs, not their absence.

> The code is a single C++ header file that's supposed to be fully-portable. I want to take this header file and add it to my own 'universal header file' which will be used on microcontrollers and desktop PC's. I've looked through the encryption header file, and I see that they use "unsigned short" for anything up to 65 thousand, and then "unsigned long" for anything up to 4 billion, so that's fine. There are however a few lines I have to tweak, such as the following:
>
> p[i] = p[i - 1] << 4u;
>
> I need to make that:
>
> p[i] = (p[i-1] << 4u) & 0xF0;
>
> To be honest, discovering a computer-and-compiler-combo with a CHAR_BIT != 8 like this is quite an experience for me. It's like I'm a biologist who's been dealing with carbon-based life forms all his life, and they've flown me in a silicon-based life form from Mars and I have it under my microscope. Twenty years is a long time to have CHAR_BIT invariably equal to 8.
>
> I'm re-writing the encryption code so that it deals in 32-Bit chunks, and I'm using 'uint_least32_t' for that purpose just in case there isn't a 32-Bit type.

If the code works fine even if "uint_least32_t" is not 32-bit, then
perhaps "uint_fast32_t" would be better - even though it is 64-bit on
some systems. (And if it won't be correct on such systems, then you
need uint32_t anyway.)

Mr Flibble

unread,
Oct 14, 2022, 9:48:03 AM10/14/22
to
On Fri, 14 Oct 2022 15:27:13 +0200
List link pointers? Again there is no reason to not use std::list with
a suitable allocator even on such resource constrained hardware and I
disagree that the resultant text size and ram usage would be any worse
than anything you could come up with by hand.

/Flibble

Mut...@dastardlyhq.com

unread,
Oct 14, 2022, 10:59:13 AM10/14/22
to
If the memory layout is hard coded at boot time why even bother pulling in
std::list or any kind of container as you don't need their generic
functionality which will almost certainly waste EEPROM space. With embedded
development you often literally have to worry about every byte you use both in
ROM and RAM and whether the mainloop is going to be fast enough to do its job.

Mr Flibble

unread,
Oct 14, 2022, 4:01:38 PM10/14/22
to
In C++ you don't pay for what you don't use: in the case of a C++ class
template only the member functions instantiated will exist in the text
segment.

/Flibble


Bonita Montero

unread,
Oct 15, 2022, 5:34:42 AM10/15/22
to
Am 13.10.2022 um 00:57 schrieb Frederick Virchanza Gotham:
> Since I started programming in C/C++ back in the early 2000's, I never encountered a compiler with CHAR_BIT anything other than 8.
>
> Well just now in the past 15 minutes, I was trying to get the code for the 'base58' algorithm to compile for the Texas Instruments F2809 microcontroller using the 'cl2000' compiler.

When you write for an architecutre that is so exoic you usually don't
need portable code. When you write for non-exotic architectures you
usually don't need portability to such exotic architectures. So you
usually don't need to care for CHAR_BIT. I've stopped using CHAR_BIT
for that and I simply write * 8 if i need the number of bits; I think
that's more readable.

Bonita Montero

unread,
Oct 15, 2022, 5:35:32 AM10/15/22
to
And you need portable code for that architectures ?

Frederick Virchanza Gotham

unread,
Oct 15, 2022, 5:53:37 AM10/15/22
to
On Saturday, October 15, 2022 at 10:35:32 AM UTC+1, Bonita Montero wrote:
> Am 13.10.2022 um 10:08 schrieb Mut:
> > A number of current Texas Instruments DSPs have 16 bit chars.
>
> And you need portable code for that architectures ?


I need to write a cryptography header file to be used on two kinds of microcontroller (Arduino with CHAR_BIT==8, Texas Instruments with CHAR_BIT==16), and also on a Desktop PC x86_64.

I've decided to deal with 32-Bit chunks at a time using uint_least32_t.

Bonita Montero

unread,
Oct 15, 2022, 5:57:33 AM10/15/22
to
Am 15.10.2022 um 11:53 schrieb Frederick Virchanza Gotham:

> I need to write a cryptography header file to be used on two kinds of microcontroller (Arduino with CHAR_BIT==8, Texas Instruments with CHAR_BIT==16), and also on a Desktop PC x86_64.

You need cryptography on a DSP ???

Frederick Virchanza Gotham

unread,
Oct 15, 2022, 6:05:32 AM10/15/22
to
On Saturday, October 15, 2022 at 10:57:33 AM UTC+1, Bonita Montero wrote:

> > I need to write a cryptography header file to be used on two kinds of microcontroller (Arduino with CHAR_BIT==8, Texas Instruments with CHAR_BIT==16), and also on a Desktop PC x86_64.
> You need cryptography on a DSP ???


Yeah I program a commercial product that is sold in two varieties (one being more expensive than the other). The hardware in both varieties is the same, it's only the firmware that's different. So if you buy the cheap one and then want to upgrade to the more expensive one, you get sent a code in an email. You enter the code into the device, it decrypts it and checks that it's correct and then unlocks the features.

Mut...@dastardlyhq.com

unread,
Oct 15, 2022, 6:28:57 AM10/15/22
to
On Fri, 14 Oct 2022 21:01:20 +0100
Same as in C obv. My issue is that it may well be built in a generic way
that will include a lot of functions that are not required if you did it
manually at the start. eg pop_front(), insert() etc.

>
>/Flibble
>


David Brown

unread,
Oct 15, 2022, 7:39:42 AM10/15/22
to
There are always /lots/ of other functions that get pulled in from
libraries. Remember, for small embedded systems the libraries are not
shared dynamic libraries that you don't see.

Just for a quick test, I made a minimal C++ main() function and compiled
for a modern microcontroller. With an empty main(), it was about 8400
bytes code of common library code. Adding a "std::list<int>" object and
using a couple of pops and pushes adds about 7 KB code to the program.

If you are making a lot of use of the standard containers, that's fine -
and there's a lot of overlap and sharing in this extra code. But in
small systems, this kind of stuff can get significant - microcontrollers
with 32 KB flash are common, and it's nice to be able to program them in
C++. In the C++ /language/, you pay very little (not quite nothing) for
features that you don't use, but that does not apply equally to the more
advanced standard library classes.

It's the same in C, of course - call just one little time conversion
function and you can find half your flash is used for locale handling
and time zones.

The needs of embedded systems vary enormously - for many, the cost in
code space or run-time efficiency for using a std::list or std::vector
is negligible. But for others, it is very far from negligible.

(It is relatively rare that you have to worry about /every/ byte of code
or data space, however - though it does happen.)




Mr Flibble

unread,
Oct 15, 2022, 7:46:05 AM10/15/22
to
On Sat, 15 Oct 2022 13:39:24 +0200
Try using std::list with a custom allocator as I originally suggested;
also your quote of 7KB sounds highly dubious and anecdotal.

/Flibble

Mut...@dastardlyhq.com

unread,
Oct 15, 2022, 11:18:45 AM10/15/22
to
You really Don't Get It do you? Stick to application programming.

Mr Flibble

unread,
Oct 15, 2022, 11:24:24 AM10/15/22
to
Of course I get it, the question is do you? The only way I can see
using a few methods from std::list taking 7KB of space is the overhead
of exception handling; perhaps Mr Brown should try it again but with
exceptions disabled and a custom allocator that allocates from an
explicit memory pool.

/Flibble

Mut...@dastardlyhq.com

unread,
Oct 15, 2022, 11:34:20 AM10/15/22
to
On Sat, 15 Oct 2022 16:24:08 +0100
I've tried to explain it to you, so has he. You've obviously never done
embedded dev, yet as usual you seem to assume you're an expert on the matter.
Believe what you like. Something to bear in mind is not all compilers and
linkers build in the same way as VC or gcc.

Mr Flibble

unread,
Oct 15, 2022, 11:39:20 AM10/15/22
to
On Sat, 15 Oct 2022 15:34:03 -0000 (UTC)
I have done embedded dev and I am well aware of its constraints; all
you have got are words completely devoid of any calories.

/Flibble

Mut...@dastardlyhq.com

unread,
Oct 15, 2022, 11:53:22 AM10/15/22
to
On Sat, 15 Oct 2022 16:39:05 +0100
Suuuuuuure you have.

Mr Flibble

unread,
Oct 15, 2022, 11:55:48 AM10/15/22
to
On Sat, 15 Oct 2022 15:53:06 -0000 (UTC)
You are just showing your ignorance of leveraging C++ in an embedded
environment.

/Flibble


Mut...@dastardlyhq.com

unread,
Oct 15, 2022, 11:57:34 AM10/15/22
to
On Sat, 15 Oct 2022 16:55:32 +0100
"Leveraging"? Run out of arguments and now resorting to buzzwords are we? :)


Mr Flibble

unread,
Oct 15, 2022, 12:00:13 PM10/15/22
to
On Sat, 15 Oct 2022 15:57:19 -0000 (UTC)
If you think the word "leveraging" is a buzzword then I can only draw
the conclusion that either English isn't your native language or you
are incredibly dumb.

/Flibble

Bonita Montero

unread,
Oct 15, 2022, 2:11:45 PM10/15/22
to
Am 15.10.2022 um 13:45 schrieb Mr Flibble:

> Try using std::list with a custom allocator as I originally suggested;
> also your quote of 7KB sounds highly dubious and anecdotal.

This doesn't work since the allocator allocates the items at at
different type than for which the allocator is specified. std::list
-Items encapsulates the type for which the list is speciefied in
another structure that has the forward and backward-pointers to
have only a single allocation and not a link-object and a T-object
which the link points separately.
So nearly all containers re-class that allocator with rebind_alloc<>.
AFAIK having a 1:1 custom allocator in that sense is only possible
with the containers that have random access iterators.

Bonita Montero

unread,
Oct 15, 2022, 2:13:24 PM10/15/22
to
Am 15.10.2022 um 17:34 schrieb Mut...@dastardlyhq.com:

> I've tried to explain it to you, so has he. You've obviously never done
> embedded dev, yet as usual you seem to assume you're an expert on the matter.
> Believe what you like. Something to bear in mind is not all compilers and
> linkers build in the same way as VC or gcc.

Are there any C++20-compliant compilers other than MSVC, g++ and clang ?
Even Intel has moved to clang and partitially LLVM.


Frederick Virchanza Gotham

unread,
Oct 15, 2022, 2:55:21 PM10/15/22
to
On Saturday, October 15, 2022 at 12:39:42 PM UTC+1, David Brown wrote:

> (It is relatively rare that you have to worry about /every/ byte of code
> or data space, however - though it does happen.)


My cryptography code is just slightly too big for the microcontroller. So I will be pinching bytes here and there.

Mr Flibble

unread,
Oct 15, 2022, 3:03:42 PM10/15/22
to
No. Obviously rebinding from T to a list node containing T can work
with a custom allocator.

/Flibble

Chris M. Thomasson

unread,
Oct 15, 2022, 4:06:25 PM10/15/22
to
Did you actually write the cipher? Or did you get the code from GitHub?

Frederick Virchanza Gotham

unread,
Oct 15, 2022, 6:42:49 PM10/15/22
to
On Saturday, October 15, 2022 at 9:06:25 PM UTC+1, Chris M. Thomasson wrote:

> Did you actually write the cipher? Or did you get the code from GitHub?


I can't find an algorithm that will fit on the microcontroller so I'm writing my own.
99% of the program memory is already taken up.

Bonita Montero

unread,
Oct 16, 2022, 1:51:35 AM10/16/22
to
I didn't say anything different.


David Brown

unread,
Oct 16, 2022, 11:04:18 AM10/16/22
to
Of course the example of 7 KB is anecdotal - I told you I made a quick
test. It doesn't get more anecdotal than that. But no, it is not
"highly dubious" - it is really what I got.

Every programmer works in a particular area, or small set of areas -
/nobody/ has experience and knowledge of all kinds of programming. The
trick to having realistic conversations and not appearing arrogant and
ignorant is to understand your limitations. You simply don't know what
you are talking about when it comes to small-systems embedded
programming, and some of the challenges or limitations involved that are
different from the kind of programming you are used to. (And similarly
there is plenty about the kind of coding /you/ do that I am ignorant about.)

So it is /fine/ for you to ask "why don't you just use a std::list with
a custom allocator". It is /not/ fine for you to claim people are wrong
when they tell you why they don't do that.

Why don't I write a custom allocator for std::list and then use that
instead of the pointer-based "home made" linked list I have now? I
don't do so because it is a lot of effort and will result in bigger,
slower, wasteful and vastly more complicated code than the two dozen or
so lines of shared C and C++ code I have at the moment that has worked
fine for the last 20+ years. It's not unlikely that with a custom
allocator and disabled exceptions I could probably get the overhead of
std::list down to 2 or 3 KB rather than 7 KB. But that only makes it
not quite as inefficient - it still is not close to the efficiency and
convenience of the custom solution. And that would come after writing
far more code to make the "standard" container work than it took to make
a completely custom solution.






Mr Flibble

unread,
Oct 16, 2022, 11:34:32 AM10/16/22
to
On Sun, 16 Oct 2022 17:03:38 +0200
So you admit that you *might* be able to get it down to 2KB; so I was
correct in my analysis and it is you who is arrogant not me. I am also
well aware of the constraints involved in embedded programming and your
assumption that I am not is another sign of your arrogance.

It is highly unlikely that your solution is more performant than
std::list; a double linked list is hardly rocket science and standard
library implementations are generally written by people who know what
they are doing.

So you can either apologize or fuck off.

/Flibble

David Brown

unread,
Oct 16, 2022, 12:52:13 PM10/16/22
to
Sorry, you seem to be having trouble understanding the conversation.
No, your analysis was not correct - the 7 KB was not "highly dubious",
but an actual measurement on real code that was compiled and linked
(with a case sample size of 1). Disabling exceptions would have been
simple, and it is common practice on small embedded systems - just as
avoiding most standard library containers (and much of the C and C++
standard libraries) is common practice on small embedded systems.
Leaving exceptions enabled is a fairer test, however, as it would be
realistic for the kind of programmer who thinks std::list<> and custom
allocators is a good idea for the task in hand.

> I am also
> well aware of the constraints involved in embedded programming and your
> assumption that I am not is another sign of your arrogance.
>

I can only assume based on what you write - and you do not write as
someone who has experience in small-systems embedded programming.

> It is highly unlikely that your solution is more performant than
> std::list; a double linked list is hardly rocket science and standard
> library implementations are generally written by people who know what
> they are doing.

It would not surprise me if my solution is an order of magnitude better
performing than std::list<>. (Not that I claim the difference would be
significant for the use in question. std::list<> is going to be pretty
efficient, but a very simple custom single linked list can be
considerably more efficient.) As you say, a linked list is not rocket
science - there's no need for custom allocators and standard library
containers when all that's needed is a "pointer to next node" field in
the node structure.

>
> So you can either apologize or fuck off.
>

You are joking, yes? You think I should apologize for your
misunderstandings, your unwarranted assumptions, your accusations of
dishonesty and your belief that you know better than anyone else about
fields of programming that are completely beyond your experience?

I'm will try to avoid posting more in this subthread unless it
contributes something positive. Hopefully you'll do the same.


David Brown

unread,
Oct 16, 2022, 1:11:04 PM10/16/22
to
This was for an Arduino, using an 8-bit AVR ? Have you much experience
with the device? And are you using the Arduino toolchain and IDE, or a
plain avr-gcc build?

The Arduino toolchain can make it difficult to optimise well - you have
limited control of the build flags. And the Ardunio libraries are
designed for ease of use for beginners, not efficiency. (At least, this
was all the case last time I tried it.)

In general for the AVR, make sure you use uint8_t types whenever
possible, as they are much more efficient than "int". Avoid pointers,
and use statically allocated data as much as you can. Make sure you
have "-fno-rtti -fno-exceptions". Check the generated assembly code -
the AVR backend is underfunded and understaffed, so though the people
who have worked on it have done a fantastic job, there are many "missed
optimisation opportunity" issues and missing peephole optimisations.
That means that sometimes small changes to the source code with no real
semantic differences can sometimes lead to significant object code
changes. Fancy branchless expressions or heavy use of tertiary
operators that give efficient results on an x86 could end up much worse
results than simple branched code. Avoid divisions, and avoid any
floating point. Remember that on this kind of device, even shift
operators are slow (especially for anything bigger than 8-bit).

Much the same applies to the TMS320 (except you want uint16_t, not
uint8_t !). But be wary of trying to read the generated TMS320 assembly
code. AVR assembly is easy to understand - TMS320 assembly will drive
you insane.


Mr Flibble

unread,
Oct 16, 2022, 1:11:56 PM10/16/22
to
On Sun, 16 Oct 2022 18:51:56 +0200
You continue to prove that you are an arrogant ass who is clueless as
far as writing performant code is concerned. Fuck off.

/Flibble


Mr Flibble

unread,
Oct 16, 2022, 2:18:51 PM10/16/22
to
On Sun, 16 Oct 2022 18:51:56 +0200
I know Fedora isn't an embedded target but I was interested to see what
the difference using std::list makes to elf binary size (symbols
stripped):

int main()
{
}

[leigh@fedora ~]$ g++ foo.cpp
[leigh@fedora ~]$ strip a.out
[leigh@fedora ~]$ ls -l a.out
-rwxr-xr-x 1 leigh leigh 14952 Oct 16 19:09 a.out

#include <list>

int main()
{
std::list<int> l;
l.push_back(42);
}

[leigh@fedora ~]$ g++ foo.cpp
[leigh@fedora ~]$ strip a.out
[leigh@fedora ~]$ ls -l a.out
-rwxr-xr-x 1 leigh leigh 15192 Oct 16 19:10 a.out

[leigh@fedora ~]$ g++ -fno-exceptions foo.cpp
[leigh@fedora ~]$ strip a.out
[leigh@fedora ~]$ ls -l a.out
-rwxr-xr-x 1 leigh leigh 15088 Oct 16 19:10 a.out

So that is just 240 extra bytes to binary file size when using
std::list ctor, dtor and push_back; and even less bytes if we disable
exceptions.

Again, feel free to apologize or fuck off; and don't assume I don't
know what I am talking about again; it is just civilised and basic good
manners to assume the person opposite isn't a dumb fuck.

/Flibble

David Brown

unread,
Oct 16, 2022, 4:02:58 PM10/16/22
to
Pure genius!

> but I was interested to see what
> the difference using std::list makes to elf binary size (symbols
> stripped):
>
> int main()
> {
> }
>
> [leigh@fedora ~]$ g++ foo.cpp

Right, so you are now trying to show something useful about code sizes
without /any/ optimisations? That's about as useful as a chocolate teapot.

And you are using /dynamic/ libraries, with code from the /dynamic/
libraries for C++ standard libraries and support code? Do you even know
what static linking is, or understand the concept of "bare metal"
coding? (Feel free to say "no" - most C++ programmers go through their
entire careers without knowing anything about such things. They are
only really relevant to small-systems embedded programmers.)

> [leigh@fedora ~]$ strip a.out
> [leigh@fedora ~]$ ls -l a.out
> -rwxr-xr-x 1 leigh leigh 14952 Oct 16 19:09 a.out
>
> #include <list>
>
> int main()
> {
> std::list<int> l;
> l.push_back(42);
> }
>

And now you have code that doesn't actually do anything, so the compiler
can remove it all.

>
> Again, feel free to apologize or fuck off; and don't assume I don't
> know what I am talking about again; it is just civilised and basic good
> manners to assume the person opposite isn't a dumb fuck.
>

I am not assuming anything - you are demonstrating it quite clearly,
again and again.



Mr Flibble

unread,
Oct 16, 2022, 4:19:21 PM10/16/22
to
On Sun, 16 Oct 2022 22:02:39 +0200
David Brown <david...@hesbynett.no> wrote:

> On 16/10/2022 20:18, Mr Flibble wrote:
> > On Sun, 16 Oct 2022 18:51:56 +0200
> > David Brown <david...@hesbynett.no> wrote:
> >
>
> >> I'm will try to avoid posting more in this subthread unless it
> >> contributes something positive. Hopefully you'll do the same.
> >
> > I know Fedora isn't an embedded target
>
> Pure genius!
>
> > but I was interested to see what
> > the difference using std::list makes to elf binary size (symbols
> > stripped):
> >
> > int main()
> > {
> > }
> >
> > [leigh@fedora ~]$ g++ foo.cpp
>
> Right, so you are now trying to show something useful about code
> sizes without /any/ optimisations? That's about as useful as a
> chocolate teapot.

See below, dumb fuck.

>
> And you are using /dynamic/ libraries, with code from the /dynamic/
> libraries for C++ standard libraries and support code? Do you even
> know what static linking is, or understand the concept of "bare
> metal" coding? (Feel free to say "no" - most C++ programmers go
> through their entire careers without knowing anything about such
> things. They are only really relevant to small-systems embedded
> programmers.)

The delta is purely the use of std::list which does not rely on any
dynamic libraries: std::allocator will likely be using the default new
operator which will likely be using std::malloc but I doubt we will
see much difference to code size if we write a custom allocator that
doesn't.

>
> > [leigh@fedora ~]$ strip a.out
> > [leigh@fedora ~]$ ls -l a.out
> > -rwxr-xr-x 1 leigh leigh 14952 Oct 16 19:09 a.out
> >
> > #include <list>
> >
> > int main()
> > {
> > std::list<int> l;
> > l.push_back(42);
> > }
> >
>
> And now you have code that doesn't actually do anything, so the
> compiler can remove it all.

And as you pointed out earlier, dumb fuck, I haven't enabled any
optimizations that would cause the code to be optimized out.

>
> >
> > Again, feel free to apologize or fuck off; and don't assume I don't
> > know what I am talking about again; it is just civilised and basic
> > good manners to assume the person opposite isn't a dumb fuck.
> >
>
> I am not assuming anything - you are demonstrating it quite clearly,
> again and again.

The only person demonstrating fucktardedness here is you. You really
should get that Dunning-Kruger Effect seen to, mate.

/Flibble


Vir Campestris

unread,
Oct 16, 2022, 4:28:51 PM10/16/22
to
I too have been in the position where every byte counts. Abbreviating
error messages was usually the easiest fix.

But...

I've also done a reasonable amount of cryptography. A home rolled
algorithm will usually have a hole in it somewhere. You'll get away with
it if the stuff you are protecting is obscure enough, and not worth a
lot, but I wouldn't trust my life or any serious amounts of money to it.

Good luck
Andy

Chris M. Thomasson

unread,
Oct 16, 2022, 4:36:44 PM10/16/22
to
Do you have any SHA2 hashes up and running on the limited space system?

Vir Campestris

unread,
Oct 16, 2022, 4:38:04 PM10/16/22
to
On 14/10/2022 08:17, Frederick Virchanza Gotham wrote:
> To be honest, discovering a computer-and-compiler-combo with a CHAR_BIT != 8 like this is quite an experience for me. It's like I'm a biologist who's been dealing with carbon-based life forms all his life, and they've flown me in a silicon-based life form from Mars and I have it under my microscope. Twenty years is a long time to have CHAR_BIT invariably equal to 8.

Pfft kids these days....

The first and third architectures I ever used had 6 bit chars
(DECSystem10 and ICL 1900). Luckily I never had to use C on them :)

Andy

Scott Lurndal

unread,
Oct 16, 2022, 5:25:15 PM10/16/22
to
Mr Flibble <fli...@reddwarf.jmc.corp> writes:
>On Sun, 16 Oct 2022 22:02:39 +0200
>David Brown <david...@hesbynett.no> wrote:

How about some real data, comparing std::list to a custom
class? This c_dlist example dates back to the late 1980s, before
std::list existed and was used in embedded (operating system
and hypervisor) code well into the second decade of the 21st
century.

============ Begin custom list example ============================

#include <stdint.h>
#include <stdio.h>

#include "include/dlist.h"

class c_task : public c_dlist
{
static const size_t MAX_NAMELEN = 32ul;

char task_name[MAX_NAMELEN];
void *task_address;
uint32_t task_priority;

public:
c_task(const char *name, uint32_t priority)
: task_address(0ul), task_priority(priority)
{ init(); snprintf(task_name, sizeof(task_name), "%s", name); }

const char *get_name(void) const { return task_name; }
uint32_t get_priority(void) const { return task_priority; }
};

int
main(int argc, const char **argv, const char **envp)
{
c_dlist listhead;
c_task task1("task1", 15);
c_task task2("task2", 20);

listhead.init();

listhead.append(&task1);
listhead.append(&task2);

c_dlist_iterator di(&listhead);
while (di.next()) {
c_task *tp = (c_task *)di.curr();

printf("Task %s, priority %u\n", tp->get_name(), tp->get_priority());
}

return 0;
}

============ Compiled with -O2, here's 'main'

0000000000400500 <main>:
400500: 55 push %rbp
400501: ba 32 00 00 00 mov $0x32,%edx
400506: b8 31 00 00 00 mov $0x31,%eax
40050b: 53 push %rbx
40050c: 48 81 ec 98 00 00 00 sub $0x98,%rsp
400513: 48 8d 5c 24 10 lea 0x10(%rsp),%rbx
400518: 48 8d 74 24 50 lea 0x50(%rsp),%rsi
40051d: 66 89 54 24 64 mov %dx,0x64(%rsp)
400522: 48 c7 44 24 40 00 00 movq $0x0,0x40(%rsp)
400529: 00 00
40052b: c7 44 24 48 0f 00 00 movl $0xf,0x48(%rsp)
400532: 00
400533: 48 89 e5 mov %rsp,%rbp
400536: c7 44 24 20 74 61 73 movl $0x6b736174,0x20(%rsp)
40053d: 6b
40053e: 66 89 44 24 24 mov %ax,0x24(%rsp)
400543: ba 14 00 00 00 mov $0x14,%edx
400548: 48 c7 84 24 80 00 00 movq $0x0,0x80(%rsp)
40054f: 00 00 00 00 00
400554: c7 84 24 88 00 00 00 movl $0x14,0x88(%rsp)
40055b: 14 00 00 00
40055f: c7 44 24 60 74 61 73 movl $0x6b736174,0x60(%rsp)
400566: 6b
400567: 48 89 64 24 10 mov %rsp,0x10(%rsp)
40056c: 48 89 5c 24 08 mov %rbx,0x8(%rsp)
400571: 48 89 5c 24 50 mov %rbx,0x50(%rsp)
400576: 48 89 64 24 58 mov %rsp,0x58(%rsp)
40057b: 48 89 74 24 18 mov %rsi,0x18(%rsp)
400580: 48 89 34 24 mov %rsi,(%rsp)
400584: eb 13 jmp 400599 <main+0x99>
400586: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40058d: 00 00 00
400590: 8b 53 38 mov 0x38(%rbx),%edx
400593: 48 89 de mov %rbx,%rsi
400596: 48 89 c3 mov %rax,%rbx
400599: 48 83 c6 10 add $0x10,%rsi
40059d: 31 c0 xor %eax,%eax
40059f: bf 40 07 40 00 mov $0x400740,%edi
4005a4: e8 27 ff ff ff callq 4004d0 <printf@plt>
4005a9: 48 39 eb cmp %rbp,%rbx
4005ac: 48 8b 03 mov (%rbx),%rax
4005af: 75 df jne 400590 <main+0x90>
4005b1: 48 81 c4 98 00 00 00 add $0x98,%rsp
4005b8: 31 c0 xor %eax,%eax
4005ba: 5b pop %rbx
4005bb: 5d pop %rbp
4005bc: c3 retq
4005bd: 0f 1f 00 nopl (%rax)

The only nonlocal branch is to the printf function.

=========Version using std::list

#include <stdint.h>
#include <stdio.h>

#include <list>

class c_task
{
static const size_t MAX_NAMELEN = 32ul;

char task_name[MAX_NAMELEN];
void *task_address;
uint32_t task_priority;

public:
c_task(const char *name, uint32_t priority)
: task_address(0ul), task_priority(priority)
{ snprintf(task_name, sizeof(task_name), "%s", name); }

const char *get_name(void) const { return task_name; }
uint32_t get_priority(void) const { return task_priority; }
};

int
main(int argc, const char **argv, const char **envp)
{
std::list<c_task> listhead;
c_task task1("task1", 15);
c_task task2("task2", 20);

listhead.push_back(task1);
listhead.push_back(task2);

std::list<c_task>::iterator it = listhead.begin();
for (; it != listhead.end(); ++it) {
c_task tp = *it;

printf("Task %s, priority %u\n", tp.get_name(), tp.get_priority());
}

return 0;
}

And here's main:
0000000000400740 <main>:
400740: 41 54 push %r12
400742: b8 31 00 00 00 mov $0x31,%eax
400747: ba 32 00 00 00 mov $0x32,%edx
40074c: 55 push %rbp
40074d: 53 push %rbx
40074e: 48 81 ec a0 00 00 00 sub $0xa0,%rsp
400755: 48 8d 7c 24 10 lea 0x10(%rsp),%rdi
40075a: 48 89 e5 mov %rsp,%rbp
40075d: 48 89 24 24 mov %rsp,(%rsp)
400761: 48 89 64 24 08 mov %rsp,0x8(%rsp)
400766: 48 c7 44 24 30 00 00 movq $0x0,0x30(%rsp)
40076d: 00 00
40076f: c7 44 24 38 0f 00 00 movl $0xf,0x38(%rsp)
400776: 00
400777: c7 44 24 10 74 61 73 movl $0x6b736174,0x10(%rsp)
40077e: 6b
40077f: 66 89 44 24 14 mov %ax,0x14(%rsp)
400784: 48 c7 44 24 60 00 00 movq $0x0,0x60(%rsp)
40078b: 00 00
40078d: c7 44 24 68 14 00 00 movl $0x14,0x68(%rsp)
400794: 00
400795: c7 44 24 40 74 61 73 movl $0x6b736174,0x40(%rsp)
40079c: 6b
40079d: 66 89 54 24 44 mov %dx,0x44(%rsp)
4007a2: e8 c9 01 00 00 callq 400970 <std::list<c_task, std::allocator<c_task> >::_M_create_node(c_task const&) [clone .isra.11]>
4007a7: 48 89 c7 mov %rax,%rdi
4007aa: 48 89 e6 mov %rsp,%rsi
4007ad: e8 4e ff ff ff callq 400700 <std::__detail::_List_node_base::_M_hook(std::__detail::_List_node_base*)@plt>
4007b2: 48 8d 7c 24 40 lea 0x40(%rsp),%rdi
4007b7: e8 b4 01 00 00 callq 400970 <std::list<c_task, std::allocator<c_task> >::_M_create_node(c_task const&) [clone .isra.11]>
4007bc: 48 89 e6 mov %rsp,%rsi
4007bf: 48 89 c7 mov %rax,%rdi
4007c2: e8 39 ff ff ff callq 400700 <std::__detail::_List_node_base::_M_hook(std::__detail::_List_node_base*)@plt>
4007c7: 48 8b 1c 24 mov (%rsp),%rbx
4007cb: 48 39 e3 cmp %rsp,%rbx
4007ce: 74 5b je 40082b <main+0xeb>
4007d0: 48 8b 43 10 mov 0x10(%rbx),%rax
4007d4: 48 8d 74 24 70 lea 0x70(%rsp),%rsi
4007d9: bf 50 0a 40 00 mov $0x400a50,%edi
4007de: 48 89 44 24 70 mov %rax,0x70(%rsp)
4007e3: 48 8b 43 18 mov 0x18(%rbx),%rax
4007e7: 48 89 44 24 78 mov %rax,0x78(%rsp)
4007ec: 48 8b 43 20 mov 0x20(%rbx),%rax
4007f0: 48 89 84 24 80 00 00 mov %rax,0x80(%rsp)
4007f7: 00
4007f8: 48 8b 43 28 mov 0x28(%rbx),%rax
4007fc: 48 89 84 24 88 00 00 mov %rax,0x88(%rsp)
400803: 00
400804: 48 8b 43 30 mov 0x30(%rbx),%rax
400808: 48 89 84 24 90 00 00 mov %rax,0x90(%rsp)
40080f: 00
400810: 48 8b 53 38 mov 0x38(%rbx),%rdx
400814: 31 c0 xor %eax,%eax
400816: 48 89 94 24 98 00 00 mov %rdx,0x98(%rsp)
40081d: 00
40081e: e8 9d fe ff ff callq 4006c0 <printf@plt>
400823: 48 8b 1b mov (%rbx),%rbx
400826: 48 39 eb cmp %rbp,%rbx
400829: 75 a5 jne 4007d0 <main+0x90>
40082b: 48 8b 3c 24 mov (%rsp),%rdi
40082f: 48 39 ef cmp %rbp,%rdi
400832: 75 0f jne 400843 <main+0x103>
400834: eb 1a jmp 400850 <main+0x110>
400836: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40083d: 00 00 00
400840: 48 89 df mov %rbx,%rdi
400843: 48 8b 1f mov (%rdi),%rbx
400846: e8 95 fe ff ff callq 4006e0 <operator delete(void*)@plt>
40084b: 48 39 eb cmp %rbp,%rbx
40084e: 75 f0 jne 400840 <main+0x100>
400850: 48 81 c4 a0 00 00 00 add $0xa0,%rsp
400857: 31 c0 xor %eax,%eax
400859: 5b pop %rbx
40085a: 5d pop %rbp
40085b: 41 5c pop %r12
40085d: c3 retq
40085e: 48 8b 3c 24 mov (%rsp),%rdi
400862: 49 89 c4 mov %rax,%r12
400865: 48 39 ef cmp %rbp,%rdi
400868: 74 0d je 400877 <main+0x137>
40086a: 48 8b 1f mov (%rdi),%rbx
40086d: e8 6e fe ff ff callq 4006e0 <operator delete(void*)@plt>
400872: 48 89 df mov %rbx,%rdi
400875: eb ee jmp 400865 <main+0x125>
400877: 4c 89 e7 mov %r12,%rdi
40087a: e8 b1 fe ff ff callq 400730 <_Unwind_Resume@plt>
40087f: 90 nop

Also compiled with -O2.

David's point seems pretty valid to me.

====== same version of the std::list, but using std::list<c_task*>:
0000000000400740 <main>:
400740: 41 54 push %r12
400742: b8 31 00 00 00 mov $0x31,%eax
400747: ba 32 00 00 00 mov $0x32,%edx
40074c: bf 18 00 00 00 mov $0x18,%edi
400751: 55 push %rbp
400752: 53 push %rbx
400753: 48 83 ec 70 sub $0x70,%rsp
400757: 48 89 e5 mov %rsp,%rbp
40075a: 48 89 24 24 mov %rsp,(%rsp)
40075e: 48 89 64 24 08 mov %rsp,0x8(%rsp)
400763: 48 c7 44 24 30 00 00 movq $0x0,0x30(%rsp)
40076a: 00 00
40076c: c7 44 24 38 0f 00 00 movl $0xf,0x38(%rsp)
400773: 00
400774: c7 44 24 10 74 61 73 movl $0x6b736174,0x10(%rsp)
40077b: 6b
40077c: 66 89 44 24 14 mov %ax,0x14(%rsp)
400781: 48 c7 44 24 60 00 00 movq $0x0,0x60(%rsp)
400788: 00 00
40078a: c7 44 24 68 14 00 00 movl $0x14,0x68(%rsp)
400791: 00
400792: c7 44 24 40 74 61 73 movl $0x6b736174,0x40(%rsp)
400799: 6b
40079a: 66 89 54 24 44 mov %dx,0x44(%rsp)
40079f: e8 7c ff ff ff callq 400720 <operator new(unsigned long)@plt>
4007a4: 48 83 f8 f0 cmp $0xfffffffffffffff0,%rax
4007a8: 74 09 je 4007b3 <main+0x73>
4007aa: 48 8d 54 24 10 lea 0x10(%rsp),%rdx
4007af: 48 89 50 10 mov %rdx,0x10(%rax)
4007b3: 48 89 c7 mov %rax,%rdi
4007b6: 48 89 ee mov %rbp,%rsi
4007b9: e8 42 ff ff ff callq 400700 <std::__detail::_List_node_base::_M_hook(std::__detail::_List_node_base*)@plt>
4007be: bf 18 00 00 00 mov $0x18,%edi
4007c3: e8 58 ff ff ff callq 400720 <operator new(unsigned long)@plt>
4007c8: 48 83 f8 f0 cmp $0xfffffffffffffff0,%rax
4007cc: 74 09 je 4007d7 <main+0x97>
4007ce: 48 8d 54 24 40 lea 0x40(%rsp),%rdx
4007d3: 48 89 50 10 mov %rdx,0x10(%rax)
4007d7: 48 89 ee mov %rbp,%rsi
4007da: 48 89 c7 mov %rax,%rdi
4007dd: e8 1e ff ff ff callq 400700 <std::__detail::_List_node_base::_M_hook(std::__detail::_List_node_base*)@plt>
4007e2: 48 8b 1c 24 mov (%rsp),%rbx
4007e6: 48 39 eb cmp %rbp,%rbx
4007e9: 74 20 je 40080b <main+0xcb>
4007eb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
4007f0: 48 8b 73 10 mov 0x10(%rbx),%rsi
4007f4: bf e0 09 40 00 mov $0x4009e0,%edi
4007f9: 31 c0 xor %eax,%eax
4007fb: 8b 56 28 mov 0x28(%rsi),%edx
4007fe: e8 bd fe ff ff callq 4006c0 <printf@plt>
400803: 48 8b 1b mov (%rbx),%rbx
400806: 48 39 eb cmp %rbp,%rbx
400809: 75 e5 jne 4007f0 <main+0xb0>
40080b: 48 8b 3c 24 mov (%rsp),%rdi
40080f: 48 39 ef cmp %rbp,%rdi
400812: 75 0f jne 400823 <main+0xe3>
400814: eb 1a jmp 400830 <main+0xf0>
400816: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40081d: 00 00 00
400820: 48 89 df mov %rbx,%rdi
400823: 48 8b 1f mov (%rdi),%rbx
400826: e8 b5 fe ff ff callq 4006e0 <operator delete(void*)@plt>
40082b: 48 39 eb cmp %rbp,%rbx
40082e: 75 f0 jne 400820 <main+0xe0>
400830: 48 83 c4 70 add $0x70,%rsp
400834: 31 c0 xor %eax,%eax
400836: 5b pop %rbx
400837: 5d pop %rbp
400838: 41 5c pop %r12
40083a: c3 retq
40083b: 48 8b 3c 24 mov (%rsp),%rdi
40083f: 49 89 c4 mov %rax,%r12
400842: 48 39 ef cmp %rbp,%rdi
400845: 74 0d je 400854 <main+0x114>
400847: 48 8b 1f mov (%rdi),%rbx
40084a: e8 91 fe ff ff callq 4006e0 <operator delete(void*)@plt>
40084f: 48 89 df mov %rbx,%rdi
400852: eb ee jmp 400842 <main+0x102>
400854: 4c 89 e7 mov %r12,%rdi
400857: e8 d4 fe ff ff callq 400730 <_Unwind_Resume@plt>
=======And the same with -fno-exceptions:
0000000000400650 <main>:
400650: 55 push %rbp
400651: b8 31 00 00 00 mov $0x31,%eax
400656: ba 32 00 00 00 mov $0x32,%edx
40065b: bf 18 00 00 00 mov $0x18,%edi
400660: 53 push %rbx
400661: 48 83 ec 78 sub $0x78,%rsp
400665: 48 89 24 24 mov %rsp,(%rsp)
400669: 48 89 64 24 08 mov %rsp,0x8(%rsp)
40066e: 48 89 e5 mov %rsp,%rbp
400671: 48 c7 44 24 30 00 00 movq $0x0,0x30(%rsp)
400678: 00 00
40067a: c7 44 24 38 0f 00 00 movl $0xf,0x38(%rsp)
400681: 00
400682: c7 44 24 10 74 61 73 movl $0x6b736174,0x10(%rsp)
400689: 6b
40068a: 66 89 44 24 14 mov %ax,0x14(%rsp)
40068f: 48 c7 44 24 60 00 00 movq $0x0,0x60(%rsp)
400696: 00 00
400698: c7 44 24 68 14 00 00 movl $0x14,0x68(%rsp)
40069f: 00
4006a0: c7 44 24 40 74 61 73 movl $0x6b736174,0x40(%rsp)
4006a7: 6b
4006a8: 66 89 54 24 44 mov %dx,0x44(%rsp)
4006ad: e8 8e ff ff ff callq 400640 <operator new(unsigned long)@plt>
4006b2: 48 83 f8 f0 cmp $0xfffffffffffffff0,%rax
4006b6: 74 09 je 4006c1 <main+0x71>
4006b8: 48 8d 4c 24 10 lea 0x10(%rsp),%rcx
4006bd: 48 89 48 10 mov %rcx,0x10(%rax)
4006c1: 48 89 c7 mov %rax,%rdi
4006c4: 48 89 ee mov %rbp,%rsi
4006c7: e8 64 ff ff ff callq 400630 <std::__detail::_List_node_base::_M_hook(std::__detail::_List_node_base*)@plt>
4006cc: bf 18 00 00 00 mov $0x18,%edi
4006d1: e8 6a ff ff ff callq 400640 <operator new(unsigned long)@plt>
4006d6: 48 83 f8 f0 cmp $0xfffffffffffffff0,%rax
4006da: 74 09 je 4006e5 <main+0x95>
4006dc: 48 8d 54 24 40 lea 0x40(%rsp),%rdx
4006e1: 48 89 50 10 mov %rdx,0x10(%rax)
4006e5: 48 89 ee mov %rbp,%rsi
4006e8: 48 89 c7 mov %rax,%rdi
4006eb: e8 40 ff ff ff callq 400630 <std::__detail::_List_node_base::_M_hook(std::__detail::_List_node_base*)@plt>
4006f0: 48 8b 1c 24 mov (%rsp),%rbx
4006f4: 48 39 eb cmp %rbp,%rbx
4006f7: 74 22 je 40071b <main+0xcb>
4006f9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
400700: 48 8b 73 10 mov 0x10(%rbx),%rsi
400704: 31 c0 xor %eax,%eax
400706: bf d0 08 40 00 mov $0x4008d0,%edi
40070b: 8b 56 28 mov 0x28(%rsi),%edx
40070e: e8 dd fe ff ff callq 4005f0 <printf@plt>
400713: 48 8b 1b mov (%rbx),%rbx
400716: 48 39 eb cmp %rbp,%rbx
400719: 75 e5 jne 400700 <main+0xb0>
40071b: 48 8b 3c 24 mov (%rsp),%rdi
40071f: 48 39 ef cmp %rbp,%rdi
400722: 75 0f jne 400733 <main+0xe3>
400724: eb 1a jmp 400740 <main+0xf0>
400726: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40072d: 00 00 00
400730: 48 89 df mov %rbx,%rdi
400733: 48 8b 1f mov (%rdi),%rbx
400736: e8 d5 fe ff ff callq 400610 <operator delete(void*)@plt>
40073b: 48 39 eb cmp %rbp,%rbx
40073e: 75 f0 jne 400730 <main+0xe0>
40073e: 75 f0 jne 400730 <main+0xe0>
400740: 48 83 c4 78 add $0x78,%rsp
400744: 31 c0 xor %eax,%eax
400746: 5b pop %rbx
400747: 5d pop %rbp
400748: c3 retq
400749: 0f 1f 00 nopl (%rax)

PS: dlist header file used above:

/*
*
* $Id: dlist.h,v 1.5 2011-07-27 23:52:17 scott Exp $
*/

#if !defined(__dlist_h_)
#define __dlist_h_

/**
* Double Linked List.
*
* Implement double linked list operations. An object that
* is included on a double-linked list derives from c_dlist.
*
* Note that locking is the responsibility of the derived class.
*
* <pre>
* class c_object: public c_dlist {
* private-data.
* public:
* public-data.
* };
* </pre>
*
* class c_object constructor or ::init function must invoked the
* c_dlist::init function to initialize the list pointers. If the
* element is not on a list, the list pointers will refer to the
* element itself. The c_dlist::is_onlist method will return <i>true</i>
* if the element is on a list, false if the element is stand-alone.
*
* The c_dlist::insert function will insert a new element before
* the object, while the c_dlist::append function will insert
* a new element after the object. This example shows an object,
* </i>object_1</i> which is already on a c_dlist listhead object
* and the code fragment will insert a new object either before or
* after the object (rather than at the beginning or end of the list).
*
* <pre>
* c_object *object_1;
* c_object *object_2;
*
* object_1.append(object_2); // Link object 2 after object 1
* object_1.insert(object_2); // Link object 2 before object 1
* </pre>
*
* The c_dlist class can also be used as a list-head object by itself,
* however, with this usage, the semantics of the c_dlist::insert and
* c_dlist::append functions change subtly; c_dlist::append will add
* the named object to the beginning of the list, while c_dlist::insert
* will add the named object to the end of the list.
*
* <pre>
* c_dlist object1_list;
* c_object *object_3;
*
* object1_list.append(object_1); // Add to start of list
* object1_list.insert(object_2); // Add to end of list
* object2.append(object_3); // Insert object 3 after object 2.
*
* Objects are removed from a list by invoking the c_dlist::remove
* function on the object being removed.
*
* <pre>
* object_1.remove(); // Remove object1 from list
* </pre>
*/
class c_dlist {
c_dlist *dl_next; ///< Forward Link
c_dlist *dl_prev; ///< Backward Link

public:
void append(c_dlist *);
void init(void);
void insert(c_dlist *);
bool is_empty(void) const;
bool is_onlist(void) const;
c_dlist *flink(void);
c_dlist *blink(void);
void remove(void);
};

/**
* Initialize a list entry. An initialized entry set so that the
* prev and next pointers refer to the element itself (e.g. this).
*/
inline void
c_dlist::init(void)
{
dl_next = dl_prev = this;
}

/**
* Get next element pointer. It is recommend that client code use
* c_dlist_iterator rather than using this function directly.
*
* @returns the next element pointer.
*/
inline c_dlist *
c_dlist::flink(void)
{
return dl_next;
}

/**
* Get previous element pointer. It is recommend that client code use
* c_dlist_iterator rather than using this function directly.
*
* @returns the previous element pointer.
*/
inline c_dlist *
c_dlist::blink(void)
{
return dl_prev;
}

/**
* Insert into double-linked list. The named element is inserted
* before the current element (e.g. <i>this</i>). If the current
* element is a c_dlist being used as a listhead, using insert will
* have the effect of adding the element to the tail of the double-linked
* list.
*
* @param dp The list element to add to the list.
*/
inline void
c_dlist::insert(c_dlist *dp)
{
dp->dl_next = this;
dp->dl_prev = dl_prev;
dl_prev->dl_next = dp;
dl_prev = dp;
}

/**
* Insert into double-linked list. The named element is inserted
* after the current element (e.g. <i>this</i>). If the current
* element is a c_dlist being used as a listhead, using append will
* have the effect of adding the element to the head of the double-linked
* list.
*
* @param dp The list element to add to the list.
*/
inline void
c_dlist::append(c_dlist *dp)
{
dp->dl_next = dl_next;
dp->dl_prev = this;
dl_next->dl_prev = dp;
dl_next = dp;
}

/**
* Remove the element from a double-linked list. This function should
* be called on the object being removed. Calling the c_dlist::remove on
* a c_dlist object being used as a listhead will result in the entire
* list becoming disconnected from the listhead, which is probably not the
* desired behavior. Thus, it is not recommended to call c_dlist::remove
* on a c_dlist being used as a listhead. Remove the objects individually
* instead.
*
* This function is safe to call during a c_dlist_iterator.
*/
inline void
c_dlist::remove(void)
{
if (dl_next == this) {
return;
}
dl_next->dl_prev = dl_prev;
dl_prev->dl_next = dl_next;
dl_prev = dl_next = this;
}

/**
* Determine if element is on a list. Return true if the element is on
* a list, false if not. When called on a c_dlist being used as a listhead,
* this function will indicate whether the list is empty or not (see
* c_dlist::is_empty()).
*
* @returns true if the element is on a list or if the listhead is non-empty
*/
inline bool
c_dlist::is_onlist(void) const
{
return dl_next != this;
}

/**
* Determine if a list is empty. Return true if the c_dlist object being
* used as a listhead has no elements.
*
* @returns true if the list is empty
*/
inline bool
c_dlist::is_empty(void) const
{
return !is_onlist();
}

/**
* Double-Linked list iterator. This class can be used to iterate over
* the members of a double-linked list as represented by a c_dlist object.
*
* The iterator allows deletion of the current element.
*
* <pre>
* c_dlist object_listhead; // List of c_objects
* c_dlist_iterator di(&object_listhead);
*
* while (di.next()) {
* c_object = (c_object *)di.curr();
*
* // operate on object.
*
* // This is safe:
* c_object->remove();
* }
* </pre>
*/
class c_dlist_iterator {
c_dlist *list;
c_dlist *current;
c_dlist *current_next;
c_dlist *current_prev;
public:
c_dlist_iterator(c_dlist *);

c_dlist *curr(void);
bool next(void);
bool prev(void);
void reset(c_dlist * = NULL);
};

/**
* Create a double linked list iterator.
*
* @param dlp The list over which to iterate
*/
inline
c_dlist_iterator::c_dlist_iterator(c_dlist *dlp)
{
list = current = dlp;
current_next = current->flink();
current_prev = current->blink();
}

/**
* Return current element. Immediately after c_dlist_iterator::reset or
* after the c_dlist_iterator::c_dlist_iterator the current element is the
* list head itself. c_dlist_iterator::next must be called to get the first
* element on the list. See example in c_dlist_iterator class documentation.
*
* @returns the current element in the iteration.
*/
inline c_dlist *
c_dlist_iterator::curr(void)
{
return current;
}

/**
* Iterate to the next element in the list. Save the next and previous
* pointers to allow the element to be deleted without perturbing the
* iteration.
*
* @returns true if the element is not the list-head
*/
inline bool
c_dlist_iterator::next(void)
{
current = current_next;
current_next = current->flink();
current_prev = current->blink();
return current != list;
}

/**
* Iterate to the previous element in the list. Save the next and previous
* pointers to allow the element to be deleted without perturbing the
* iteration.
*
* @returns true if the element is not the list-head
*/
inline bool
c_dlist_iterator::prev(void)
{
current = current_prev;
current_next = current->flink();
current_prev = current->blink();
return current != list;
}

/**
* Reset the iterator to the head of the list.
*/
inline void
c_dlist_iterator::reset(c_dlist *new_listhead)
{
if (new_listhead != NULL) {
list = new_listhead;
}
current = list;
current_next = current->flink();
current_prev = current->blink();
}
#endif /* !defined(__dlist_h_) */
/* vim: sw=4 sts=4 sta ts=8:
*/

Chris M. Thomasson

unread,
Oct 16, 2022, 5:38:24 PM10/16/22
to
On 10/16/2022 2:24 PM, Scott Lurndal wrote:
> Mr Flibble <fli...@reddwarf.jmc.corp> writes:
>> On Sun, 16 Oct 2022 22:02:39 +0200
>> David Brown <david...@hesbynett.no> wrote:
>
> How about some real data, comparing std::list to a custom
> class? This c_dlist example dates back to the late 1980s, before
> std::list existed and was used in embedded (operating system
> and hypervisor) code well into the second decade of the 21st
> century.
[...]
> inline bool
> c_dlist_iterator::prev(void)
> {
> current = current_prev;
> current_next = current->flink();
> current_prev = current->blink();
> return current != list;
^^^^^^^^^^^^^^^^^
Humm. For some reason flink and blink remind me of the lock-free
Microsoft SList API:

https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/singly-and-doubly-linked-lists

Flink and Blink. ;^)

Mr Flibble

unread,
Oct 16, 2022, 5:40:15 PM10/16/22
to
On Sun, 16 Oct 2022 21:24:59 GMT
sc...@slp53.sl.home (Scott Lurndal) wrote:

> Mr Flibble <fli...@reddwarf.jmc.corp> writes:
> >On Sun, 16 Oct 2022 22:02:39 +0200
> >David Brown <david...@hesbynett.no> wrote:
>
> How about some real data, comparing std::list to a custom
> class? This c_dlist example dates back to the late 1980s, before
> std::list existed and was used in embedded (operating system
> and hypervisor) code well into the second decade of the 21st
> century.

You are not comparing like with like: that antiquated C thing is an
intrusive list so a better comparison would be with
boost::intrusive::list rather than with std::list.

/Flibble

Chris M. Thomasson

unread,
Oct 16, 2022, 5:49:15 PM10/16/22
to
Ahhh, I forgot that the lock-free version is in their:
_________________
[...]
Sequenced Singly Linked Lists

A sequenced singly linked list is an implementation of singly linked
lists that supports atomic operations. It is more efficient for atomic
operations than the implementation of singly linked lists described in
Singly Linked Lists.
[...]
_________________

funny how MS words it... ;^)

Scott Lurndal

unread,
Oct 16, 2022, 7:49:32 PM10/16/22
to
Mr Flibble <fli...@reddwarf.jmc.corp> writes:
>On Sun, 16 Oct 2022 21:24:59 GMT
>sc...@slp53.sl.home (Scott Lurndal) wrote:
>
>> Mr Flibble <fli...@reddwarf.jmc.corp> writes:
>> >On Sun, 16 Oct 2022 22:02:39 +0200
>> >David Brown <david...@hesbynett.no> wrote:
>>
>> How about some real data, comparing std::list to a custom
>> class? This c_dlist example dates back to the late 1980s, before
>> std::list existed and was used in embedded (operating system
>> and hypervisor) code well into the second decade of the 21st
>> century.
>
>You are not comparing like with like: that antiquated C thing is an
>intrusive list so a better comparison would be with
>boost::intrusive::list rather than with std::list.

I fail to see what the added complexity buys me. "Antiquated C thing"
is completely irrelevent; it is fully legal C++.

Juha Nieminen

unread,
Oct 17, 2022, 2:18:32 AM10/17/22
to
Bonita Montero <Bonita....@gmail.com> wrote:
> Am 15.10.2022 um 11:53 schrieb Frederick Virchanza Gotham:
>
>> I need to write a cryptography header file to be used on two kinds of microcontroller (Arduino with CHAR_BIT==8, Texas Instruments with CHAR_BIT==16), and also on a Desktop PC x86_64.
>
> You need cryptography on a DSP ???

I think you should take to heart the saying "better to remain silent and
be thought a fool than to speak and remove all doubt".

David Brown

unread,
Oct 17, 2022, 3:54:23 AM10/17/22
to
On 17/10/2022 01:49, Scott Lurndal wrote:
> Mr Flibble <fli...@reddwarf.jmc.corp> writes:
>> On Sun, 16 Oct 2022 21:24:59 GMT
>> sc...@slp53.sl.home (Scott Lurndal) wrote:
>>
>>> Mr Flibble <fli...@reddwarf.jmc.corp> writes:
>>>> On Sun, 16 Oct 2022 22:02:39 +0200
>>>> David Brown <david...@hesbynett.no> wrote:
>>>
>>> How about some real data, comparing std::list to a custom
>>> class? This c_dlist example dates back to the late 1980s, before
>>> std::list existed and was used in embedded (operating system
>>> and hypervisor) code well into the second decade of the 21st
>>> century.
>>
>> You are not comparing like with like: that antiquated C thing is an
>> intrusive list so a better comparison would be with
>> boost::intrusive::list rather than with std::list.
>
> I fail to see what the added complexity buys me. "Antiquated C thing"
> is completely irrelevent; it is fully legal C++.

Exactly - there is no need to change straightforward working code that
does all it needs to do. Even when starting from scratch, it is
important to consider the trade-offs - if a custom solution is more
efficient, and efficiency is a concern for the code in question, then
that's a point in its favour over standard solutions.

For my own use in this particular case, I don't even need a
double-linked list - I just need a list that I can add to, iterate
through, and very occasionally delete from. (I believe it has been
obvious from my first descriptions that I had an intrusive list.)

David Brown

unread,
Oct 17, 2022, 4:09:55 AM10/17/22
to
From his description, it sounds like the encryption does not have to
cover more than a small code key. That reduces the risk somewhat - many
attacks on encryption systems rely on sending specially crafted packets,
or examining long encrypted streams where you can guess some of the
original content (like html tags). For a short enough message, sent
rarely, it's probably enough to xor the message bytes with the results
of a pseudorandom generator. You don't need to re-implement OpenSSL for
a 16 byte message.

Still, it's a very good point you make - good encryption implementations
are not always easy even if you have all the details of the algorithm.

If the hardware is still in flux, an option is an external encryption
chip. You can get small and cheap devices that are easy to integrate
with such microcontrollers - Microchip (the manufacturers of the AVR in
the Arduino) have them.

Mut...@dastardlyhq.com

unread,
Oct 17, 2022, 11:27:37 AM10/17/22
to
On Sat, 15 Oct 2022 16:59:56 +0100
Mr Flibble <fli...@reddwarf.jmc.corp> wrote:
>On Sat, 15 Oct 2022 15:57:19 -0000 (UTC)
>Mut...@dastardlyhq.com wrote:
>> >You are just showing your ignorance of leveraging C++ in an embedded
>> >environment.
>>
>> "Leveraging"? Run out of arguments and now resorting to buzzwords are
>> we? :)
>
>If you think the word "leveraging" is a buzzword then I can only draw
>the conclusion that either English isn't your native language or you
>are incredibly dumb.

Its just buzzword bullshit, used by people who don't know what they're talking
about in order to sound intelligent. Its just a fancy way of saying "using"
but that sounds so mundane, right?

Mut...@dastardlyhq.com

unread,
Oct 17, 2022, 11:29:26 AM10/17/22
to
Proving yet again what an arrogant moron you are. Plus ca change.

daniel...@gmail.com

unread,
Oct 17, 2022, 12:05:06 PM10/17/22
to
On Monday, October 17, 2022 at 11:27:37 AM UTC-4, Mut...@dastardlyhq.com wrote:
>
> Its [leveraging] just buzzword bullshit, used by people who don't know what they're talking
> about in order to sound intelligent.

:-)

I recall one day in a meeting explaining something about a .Net user interface I was
working on, and the boss asked, "have you leveraged the HTML?"

Daniel

Mut...@dastardlyhq.com

unread,
Oct 17, 2022, 12:13:24 PM10/17/22
to
Did he maybe have a vision that he wanted to whiteboard in order to drill down
and run with the mission statement? :)


Mr Flibble

unread,
Oct 17, 2022, 12:31:28 PM10/17/22
to
On Mon, 17 Oct 2022 09:54:03 +0200
No you didn't make it obvious that you wanted an intrusive list because
if you did we wouldn't have ended up talking about std::list.

/Flibble

Mr Flibble

unread,
Oct 17, 2022, 12:33:18 PM10/17/22
to
I believed I have shown that his figures are bullshit which makes him
and by association yourself the morons.

/Flibble

red floyd

unread,
Oct 17, 2022, 12:44:49 PM10/17/22
to
I think he just wanted to actualize the synergies.


Mr Flibble

unread,
Oct 17, 2022, 12:47:44 PM10/17/22
to
On Mon, 17 Oct 2022 09:44:31 -0700
red floyd <no.spa...@its.invalid> wrote:

> On 10/17/2022 9:13 AM, Mut...@dastardlyhq.com wrote:
> > On Mon, 17 Oct 2022 09:04:57 -0700 (PDT)
> > "daniel...@gmail.com" <daniel...@gmail.com> wrote:
> >> On Monday, October 17, 2022 at 11:27:37 AM UTC-4,
> >> Mut...@dastardlyhq.com wrote:
> >>>
> >>> Its [leveraging] just buzzword bullshit, used by people who don't
> >>> know what
> >> they're talking
> >>> about in order to sound intelligent.
> [...]
> >
> > Did he maybe have a vision that he wanted to whiteboard in order to
> > drill down and run with the mission statement? :)
> >
>
> I think he just wanted to actualize the synergies.

The word "leverage" is NOT a buzzword.

/Flibble

David Brown

unread,
Oct 17, 2022, 1:56:28 PM10/17/22
to
I wrote "You make your timer class have the required list link pointers
in the class, have each registering function declare their timer object
with static lifetime, and your registration function links them
together". That is a quotation from the post before /you/ started
talking about std::list, saying "List link pointers? Again there is no
reason not to use std::list with a suitable allocator".

Given that you quoted my slightly odd-sounding "list link pointers"
phrase, I assume you read that the pointers were in the class. Did you
also notice I said you would make the timer objects /static/, thus there
is no allocation at runtime, and no use for an allocator?

Maybe it wasn't obvious. I thought it was, but it's up to others to judge.



Lynn McGuire

unread,
Oct 17, 2022, 4:24:59 PM10/17/22
to
Yup, I used six bit bytes, 6 byte words (36 bits), on Univac 1108s. We
also had six bit bytes with 10 byte words (60 bits), on CDC 7600s. Big
beautiful iron. Unfortunately, we had to abandon the Univac 1108 in
1982 when our code and data exceeded 2 MB on that platform. We bought a
32 bit Prime 450 in 1977, upgraded to a Prime 750 in 1980, and a Prime
2250 in 1983 ??? We ported to a customer's Vax VMS box in 1985 ??? All
Fortran platforms.

Lynn

Lynn McGuire

unread,
Oct 17, 2022, 4:29:53 PM10/17/22
to
On 10/15/2022 4:57 AM, Bonita Montero wrote:
> Am 15.10.2022 um 11:53 schrieb Frederick Virchanza Gotham:
>
>> I need to write a cryptography header file to be used on two kinds of
>> microcontroller (Arduino with CHAR_BIT==8, Texas Instruments with
>> CHAR_BIT==16), and also on a Desktop PC x86_64.
>
> You need cryptography on a DSP ???

Every one need cryptography. If you are processing in the clear then
you will be owned sooner or later.

Lynn

Manfred

unread,
Oct 17, 2022, 7:11:00 PM10/17/22
to
You are lacking a vision of the synergies ;)

Chris M. Thomasson

unread,
Oct 17, 2022, 7:22:50 PM10/17/22
to
Apoplectic synergistic energy formations flowing within n-ary space...

Paul N

unread,
Oct 18, 2022, 8:13:18 AM10/18/22
to
When I first saw "role model" used as a verb I thought "No, I'm not going to let this become a phrase". But it seems I failed. I wonder if my managers have any idea why I put "Strongly disagree" whenever a survey asks me whether I think top management role model the corporate values.

Mut...@dastardlyhq.com

unread,
Oct 18, 2022, 11:04:19 AM10/18/22
to
When its used in place of "use" then thats exactly what it is. Leverage is
the outcome of using a lever, not a programming language.

Mr Flibble

unread,
Oct 18, 2022, 12:40:23 PM10/18/22
to
On Tue, 18 Oct 2022 15:04:01 -0000 (UTC)
Mut...@dastardlyhq.com wrote:

> On Mon, 17 Oct 2022 17:47:27 +0100
> Mr Flibble <fli...@reddwarf.jmc.corp> wrote:
> >On Mon, 17 Oct 2022 09:44:31 -0700
> >red floyd <no.spa...@its.invalid> wrote:
> >
> >> On 10/17/2022 9:13 AM, Mut...@dastardlyhq.com wrote:
> >> > On Mon, 17 Oct 2022 09:04:57 -0700 (PDT)
> >> > "daniel...@gmail.com" <daniel...@gmail.com> wrote:
> >> >> On Monday, October 17, 2022 at 11:27:37 AM UTC-4,
> >> >> Mut...@dastardlyhq.com wrote:
> >> >>>
> >> >>> Its [leveraging] just buzzword bullshit, used by people who
> >> >>> don't know what
> >> >> they're talking
> >> >>> about in order to sound intelligent.
> >> [...]
> >> >
> >> > Did he maybe have a vision that he wanted to whiteboard in order
> >> > to drill down and run with the mission statement? :)
> >> >
> >>
> >> I think he just wanted to actualize the synergies.
> >
> >The word "leverage" is NOT a buzzword.
>
> When its used in place of "use" then thats exactly what it is.
> Leverage is the outcome of using a lever, not a programming language.

Yes leverage is the outcome of using a lever which is why it is a
perfectly cromulent word to use when describing using a METAPHORICAL
lever. It is NOT a buzzword.

/Flibble


daniel...@gmail.com

unread,
Oct 18, 2022, 3:15:06 PM10/18/22
to
On Tuesday, October 18, 2022 at 12:40:23 PM UTC-4, Mr Flibble wrote:

> Yes leverage is the outcome of using a lever which is why it is a
> perfectly cromulent word to use when describing using a METAPHORICAL
> lever. It is NOT a buzzword.
>
It's leveraging the English ...

Mut...@dastardlyhq.com

unread,
Oct 19, 2022, 11:12:26 AM10/19/22
to
On Tue, 18 Oct 2022 17:40:05 +0100
Cromulent? Did you just flip a dictionary open at a random page or are you
just taking the piss?

>lever. It is NOT a buzzword.

Lever implies doing something you couldn't do before without it. It does not
apply in this case ergo you're just using it as a buzzword in order to try
and sound smart. Didn't work.


Scott Lurndal

unread,
Oct 19, 2022, 11:36:18 AM10/19/22
to
In this case, the use of "Cromulent" was perfectly cromulent :-)

The term originally was coined by a Simpsons writer, and has
subsequently reached the Merriam-Webster dictionary.

Mut...@dastardlyhq.com

unread,
Oct 20, 2022, 12:16:43 PM10/20/22
to
Rather apt I suppose given Flibble does seem to impersonate Bart :)

Tim Rentsch

unread,
Nov 2, 2022, 8:46:59 PM11/2/22
to
Frederick Virchanza Gotham <cauldwel...@gmail.com> writes:

> On Thursday, October 13, 2022, Juha Nieminen wrote:
>
>> The vast, *vast* majority of C and C++ programmers assume that 'char'
>> is always 8-bit, and sometimes write code making that assumption.
>> It's *extremely* rare to see any code out there that uses CHAR_BIT at
>> all, but it's quite common to see code that assumes that it's 8.
>> Most C and C++ programmers just assume that it's a de-facto universal
>> standard, and that the actual C and C++ standards are just antiquated
>> in this regard, by keeping "backwards compatibility" with some more
>> exotic CPUs from the 1970's that have been completely obsolete for
>> decades.
>>
>> I suppose there's a good reason why the language standards don't
>> assume that 'char' is 8 bits, after all.
>
> I totally agree. I've been using C++ compilers for about 20 years
> now, and yesterday was the first time I encountered CHAR_BIT != 8.
> Lots of my code uses "char unsigned" and "uint8_t" interchangeably.
>
>
> On Thursday, October 13, 2022, Mut...@... wrote:
>
>> A number of current Texas Instruments DSPs have 16 bit chars.
>>
>> Personally I always use int8_t or uint8_t if I'm writing portable
>> code just to be 100% sure.
>
> I'm writing a 'universal header file' today that will be used in a
> program on:
> 1) x86_64 desktop PC
> 2) microcontroller Texas Instruments F2809 (with 16-Bit bytes)
> 3) microcontroller Arduino sam3x8e
>
> If I include "cstdint", then it doesn't have "uint8_t" on the Texas
> Instruments compiler. So I'm using "uint_least8_t" in the code.

Easier just to use unsigned char.

Tim Rentsch

unread,
Nov 16, 2022, 8:42:18 AM11/16/22
to
Paavo Helde <ees...@osa.pri.ee> writes:

> 14.10.2022 08:54 Juha Nieminen kirjutas:
>
>> David Brown <david...@hesbynett.no> wrote:
>>
>>> It is very rare that "as portable as possible" is a realistic
>>> specification. It happens, but it is not common.
>>
>> "Not common" does not mean "you shouldn't care", when you are writing
>> a library that could potentially be used in more exotic architectures,
>> such as the one mentioned in this thread.
>>
>> For example if you are writing, say, a small library that
>> calculates hashes or checksums using a particular algorithm. It's
>> not at all unrealistic that such a library could have uses in these
>> more exotic microcontrollers (as microcontrollers are often used in
>> embedded systems that handle data somehow, and might be interested
>> in calculating things like checksums and hashes). And it is quite
>> likely that such an algorithm might care about bit sizes.
>
> True, but for really supporting such exotic platforms one would need
> to run tests on these platforms (or at least in an emulator) during
> the development and potentially also later if anything changes.

Perhaps some tests, but not necessarily all tests. Any parts of
the program that are verifiably platform agnostic would not need
platform-specific re-testing. Also, any platform-specific tests
don't have to be run during development, but only just before the
program is deployed on the exotic platforms in question, which
could be significantly later than the original development.

> Software without tests is just a work of literature.

A hyperbolic statement if ever there was one.

Michael S

unread,
Nov 16, 2022, 9:25:05 AM11/16/22
to
On Thursday, October 13, 2022 at 3:16:54 A
> Apparently the TMS320C28x is a DSP (Digital Signal Processor). I've
> heard that it's common for CHAR_BIT to be 16 or 32 in implementations
> for DSPs.
>

Late reaction, sorry.
No, TMS320C28xx, a.k.a. C2000 is not a DSP. It's a microcontroller
with DSP linage. C28 architecture is a 32-bit extension of C24
architecture which, in turn, is a derivative of TMS320C10 architecture
of early 1980s that was a [world's first popular] DSP.
TMS320C55xx, a.k.a. C5000 is another extant derivative TMS320C10
(via C25 and C54). This one is a DSP.

Why one is DSP and another is microcontroller?
Mostly because TI decided to call them taht way.
It is possible to find technical justifications as well, in their respective
architectures, micro-architectures and especially in sets of peripheral,
but all that is secondary to the will of manufacturer.


> --
> Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
> Working, but not speaking, for Philips
> void Void(void) { Void(); } /* The recursive call of the void */

Keith Thompson

unread,
Nov 16, 2022, 1:38:45 PM11/16/22
to
How do you know that a part of program is "verifiably platform agnostic"
without platform-specific testing? How else would that be verified?

>> Software without tests is just a work of literature.
>
> A hyperbolic statement if ever there was one.

Sure, but only slightly hyperbolic.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for XCOM Labs

David Brown

unread,
Nov 17, 2022, 5:04:58 AM11/17/22
to
On 16/11/2022 15:24, Michael S wrote:
> On Thursday, October 13, 2022 at 3:16:54 A
>> Apparently the TMS320C28x is a DSP (Digital Signal Processor). I've
>> heard that it's common for CHAR_BIT to be 16 or 32 in implementations
>> for DSPs.
>>
>
> Late reaction, sorry.
> No, TMS320C28xx, a.k.a. C2000 is not a DSP. It's a microcontroller
> with DSP linage. C28 architecture is a 32-bit extension of C24
> architecture which, in turn, is a derivative of TMS320C10 architecture
> of early 1980s that was a [world's first popular] DSP.
> TMS320C55xx, a.k.a. C5000 is another extant derivative TMS320C10
> (via C25 and C54). This one is a DSP.
>
> Why one is DSP and another is microcontroller?
> Mostly because TI decided to call them taht way.
> It is possible to find technical justifications as well, in their respective
> architectures, micro-architectures and especially in sets of peripheral,
> but all that is secondary to the will of manufacturer.
>

It is a DSP, not a microcontroller - mostly because /I/ decide to call
them that way :-)

Of course there is no precise and universally agreed-upon distinction.
Typical microcontroller traits are integrated peripherals (UART, I²C,
SPI, PWM, Timers, CAN, etc.) and integrated memory. From that
viewpoint, they are microcontrollers. Typical DSP traits are
specialised processor cores with instructions and hardware targeting
maximum throughput of FIR, IIR, FFT and other "DSP" algorithms, often at
the expense of convenience of more "normal" code.

The core of these devices (at least on the TMS320F24x device I have
used) is clearly DSP oriented. It is very efficient for DSP style code,
but a mess for more "random" stuff - trying to deal with 8-bit data, for
example, is horrible.

Probably the best way to describe these devices is microcontrollers with
DSP cores.

Mut...@dastardlyhq.com

unread,
Nov 17, 2022, 11:40:18 AM11/17/22
to
On Thu, 17 Nov 2022 11:04:42 +0100
David Brown <david...@hesbynett.no> wrote:
>On 16/11/2022 15:24, Michael S wrote:
>> On Thursday, October 13, 2022 at 3:16:54 A
>>> Apparently the TMS320C28x is a DSP (Digital Signal Processor). I've
>>> heard that it's common for CHAR_BIT to be 16 or 32 in implementations
>>> for DSPs.
>>>
>>
>> Late reaction, sorry.
>> No, TMS320C28xx, a.k.a. C2000 is not a DSP. It's a microcontroller
>> with DSP linage. C28 architecture is a 32-bit extension of C24
>> architecture which, in turn, is a derivative of TMS320C10 architecture
>> of early 1980s that was a [world's first popular] DSP.
>> TMS320C55xx, a.k.a. C5000 is another extant derivative TMS320C10
>> (via C25 and C54). This one is a DSP.
>>
>> Why one is DSP and another is microcontroller?
>> Mostly because TI decided to call them taht way.
>> It is possible to find technical justifications as well, in their respective
>> architectures, micro-architectures and especially in sets of peripheral,
>> but all that is secondary to the will of manufacturer.
>>
>
>It is a DSP, not a microcontroller - mostly because /I/ decide to call
>them that way :-)
>
>Of course there is no precise and universally agreed-upon distinction.
>Typical microcontroller traits are integrated peripherals (UART, I²C,
>SPI, PWM, Timers, CAN, etc.) and integrated memory. From that

To be fair a lot of microcontrollers have those too. I would define a DSP as
something that can do ADC and/or DAC itself, ie it can process external data
directly and the TI chips AFAIK can do that.

Richard Damon

unread,
Nov 17, 2022, 11:24:03 PM11/17/22
to
Analog <-> Digital conversion is not what makes a DSP a DSP. MANY
ordinary microcontrollers have analog devices built in.

DSP chips tend to be one optimized to do Multiply and Accumulate
operations, particularly between vectors of values.

David Brown

unread,
Nov 18, 2022, 2:16:44 AM11/18/22
to
Yes. "DSP" is an aspect of the core and surrounding parts (such as
specialised memory blocks). It means /Digital/ Signal Processing - it
is independent of whether the device has /analogue/ signal handling.
(Most serious DSP's don't, as the kind of device and surrounding
electronics and layout that you need for quality analogue is very
different from what you need for the digital parts of your system.)


Michael S

unread,
Nov 18, 2022, 6:47:11 AM11/18/22
to
In practice, stand-alone DSP chips almost never had on-chip ADCs
or DACs.
Not because they didn't want, but because it precludes implementation
on relatively modern silicon processes. And it is quite important for
DSPs to be implemented on relatively modern process, because
MOPs/Watt is far more important selling point for DSP than for MCU.

All that applies to 1980 to ~2005.
Later on stand-alone DSPs turned into shrinking and fragmenting niches.
And after both leading manufacturers of stand-alone DSPs left
the race for finer geometries, it became even harder to spot any trends.

Scott Lurndal

unread,
Nov 18, 2022, 9:52:51 AM11/18/22
to
Michael S <already...@yahoo.com> writes:
>On Friday, November 18, 2022 at 6:24:03 AM UTC+2, Richard Damon wrote:

>> DSP chips tend to be one optimized to do Multiply and Accumulate=20
>> operations, particularly between vectors of values.
>
>In practice, stand-alone DSP chips almost never had on-chip ADCs
>or DACs.
>Not because they didn't want, but because it precludes implementation
>on relatively modern silicon processes. And it is quite important for
>DSPs to be implemented on relatively modern process, because=20
>MOPs/Watt is far more important selling point for DSP than for MCU.
>
>All that applies to 1980 to ~2005.
>Later on stand-alone DSPs turned into shrinking and fragmenting niches.=20
>And after both leading manufacturers of stand-alone DSPs left
>the race for finer geometries, it became even harder to spot any trends.

Nowadays one just licenses the IP from Tensilica or Ceva and tape it
out as part of a larger SoC package.

Mut...@dastardlyhq.com

unread,
Nov 18, 2022, 11:32:55 AM11/18/22
to
Using that definition x86 post pentium are DSPs.

Mut...@dastardlyhq.com

unread,
Nov 18, 2022, 11:33:50 AM11/18/22
to
You won't be processing any signals if you can't get the data which 99% of
the time will be originating in the analogue realm.

It is loading more messages.
0 new messages