Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> To beginners it might seem like “wasting memory” by using a 32-bit boolean

Maybe I'm a beginner then. He lists a few cases where it's not worse than sticking to 8-bit bools, but no cases where it's actually an improvement. It still wastes memory sometimes, e.g. if you have adjacent booleans in a struct, or boolean variables in a function that spill out of registers onto the stack. Sure it's only a few bytes here and there, but why pessimize? What do you gain from using a larger size?



It depends entirely on the architectures | CPUs, that said the obvious case from past experience is numeric processsing jobs where (say) you flow data into "per cycle" structs that lead with some conditionals and fill out with (say) 512 | 1024 | 2048 sample points for that cycle (32 or 64 bit ints or floats) .. the 'meat' of the per cycle job.

My specific bug bear here was a junior who insisted "saving space" by packing the structs and using a single 8 bit byte for the conditionals.

Their 'improved' code ground throughput on intel chips by a factor of 10 or so and generated BUS ERRORs on SPARC RISC architectures.

By packing the header of the structs they misaligned the array of data values such that the intel chips were silently fetching two 32 bit words (say) to get half a word from each to splice together to form a 32 bit data value (that was passed straddling a word boundary) to pipe into the ALU and then do something similar to repack on the other end - SPARC's quite sensibly were throwing a fit at non aligned data.

Point being - sometimes it makes sense to fit data to the architecture and not pack data to "save" space (this is all for throughput piped calculations not long term file storage in any case)


This is the use case for `uint_fast8_t` (part of the C99 standard); it should use whatever width of unsigned integer is enough to store a byte, but fastest for the platform. You always know that the type can be serialized as 8 bits, but it might be larger in memory. So long as you don't assume too much about your struct sizes across platforms, it should be a good choice for this. Although, if alignment is an issue, it might be a bit more complicated depending on platform.


10 years ago when ATmegas were still around and your 32 bit variable was generating 3 instructions for addition I would say „right on“ but now everything is a 32 bit Cortex-M and please stop polluting your code with this nonsense


Please understand, I am still in a position where I am writing new code for a platform which only has one compiler, a proprietary fork of GCC from nearly 20 years ago. I assume other C programmers might have similar situations.


> a proprietary fork of GCC

A what now?


I think it's not a GPL violation if you keep the fork non-public.

Though I'm entirely sure not when something is considered private or public. You can obviously make changes to a GPL repo, compile it and run the executable yourself and just never release the source code.

But what happens when you start sharing the executable with your friends, or confine it to a company?

"I made this GCC fork with some awesome features. You can contact me at joe@gmail.com if you're intere$ted ;)"


My understanding is that the GPL only requires the source code to be made available on request for at least 3 years (or as long as you support the software, if more than 3 years). If you want to require people who want the source to write to you via the Post Office and pay shipping+handling+cost of a disc to receive the source code, I believe this is permitted by the GPL as long as you don't profit off of the cost.

Of course, for almost all practical cases, the source code for a GPLed program is made available as a download off the Internet because the mail order disc route seems really archaic these days and probably would be removed altogether in a GPL version 4 if some prominent company used this loophole to evade the spirit of the GPL. Either that or somebody would jump through your hoops to get the source and just stick it on a public GitHub repo. If you then DMCA that repo, you'd be in violation of the GPL.

If you share an GPLed executable with your friends or with other people at a company, then they'd presumably be able to request the source code. But if you run a Cloud GCC service with your fork, you could get away with keeping your source code proprietary because GCC isn't under AGPL.


All the GPL says on source code access is that you need to make the source code available to whoever you distributed your program to. If the program never leaves a closed circle of people, neither does the source code.


My understanding is the violation happens when you share the binary without the license and sources, or information on how to request the sources.


For example, Microchip XC16 [1]. It is GCC with changes to support their PIC processors. Some of the changes introduce bugs, for example (at least as of v1.31) the linker would copy the input linker script to a temporary location while handling includes or other pre-processor macros in the linker script. Of course if you happen to run two instances at exactly the same time one of them fails.

As far as the licensing part goes they give you the source code, but last time I tried I could not get it to compile. Kind of lame and sketchy in my opinion.

[1] https://www.microchip.com/en-us/tools-resources/develop/mpla...


"Everything is 32-bit Cortex-M" isn't true and it's not even close.


IDK it seems semantically right


But if you don't use packed attributes, then the compiler will still add padding as necessary to avoid misalignment, while not wasting space when that's not necessary.


The key part (for myself) of ForkMeOnTinder's comment was:

> Maybe I'm a beginner then. He lists a few cases where it's not worse than sticking to 8-bit bools, but no cases where it's actually an improvement. It still wastes memory sometimes

They key part of my response is sometimes "wasting memory" (to gain alignment) is a good thing.

If someone, a beginner, is concerned about percieved wasted memory then of course they will use "packed".

As for the guts of your comment, I agree with your sentiment but would exercise caution about expecting a compiler to do what you expect in practice - especially for cross architectural projects that are intended to be robust for a decade and more - code will be put through muliple compilers across multiple architectures and potentially many many flags will be appied that may conflict in unforseen ways with each other.

In general I supported the notion of sanity check routines that double check assumptions at runtime, if you want data aligned, require data to be big endian or small endian etc then have some runtime sanity checks that can verify this for specific executables on the target platform


If you have three chars next to each other in a struct, there's a good chance they'll take 4 bytes of memory due to padding. 4 32-bit bools guarantee it'll take 12 at least, if not 16.


At one point a loooooong time ago we said "let's give every struct its own page" as a joke but... holy crap, it was so much faster.


Most of the time an easy optimization is to pad fields of your struct to a 32 bit boundary. Almost any compiler will do this for you (look up "struct alignment / padding"). If the compiler is going to do this anyway, might as well use the memory yourself instead of letting it be empty space. If it doesn't happen, you leave performance on the table, so doing this raises the chance that your struct/fields will be aligned.

Nuance is that each field should be at an address divisible by the fields size or wordline size, not some magic 32 constant. The entire struct should also be padded to a multiple of the largest fields size. In practice this usually means 32 bit alignment.

Ref http://www.catb.org/esr/structure-packing/


And to add to that, if you use an actual bool type, sanitizers will warn you if they are ever any value other than false (0) or true (1).


Computer architecture is optimized for 32+ bit aligned access to most things. The gain is (usually, but not always!) performance.


I'm afraid you are only slightly correct.

Architectures are generally optimized for aligned access (or disallow unaligned access), but what counts as "aligned" is different for each type.

A char type that is used for a bool can be accessed on any byte boundary because the alignment of a char is 1. The alignment of a 32-bit value is 4.

However, architectures are generally more optimized for 32-bit operations in registers. If you're dealing with a char in a register, the compiler will generally treat it as a 32-bit value, clearing the top bits. (This is one of those places where C's UB can bite you.)

However, there are architectures where 32-bit access is optimized.


What's an example of a function where a boolean variable spills to the stack and the 3 bytes are important?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: