[HN Gopher] Comp.lang.c Frequently Asked Questions
___________________________________________________________________
Comp.lang.c Frequently Asked Questions
Author : hliyan
Score : 85 points
Date : 2021-09-12 16:20 UTC (6 hours ago)
(HTM) web link (c-faq.com)
(TXT) w3m dump (c-faq.com)
| hulitu wrote:
| Also worth reading is C infrequently asked questions
| https://www.seebs.net/faqs/c-iaq.html
| BenjiWiebe wrote:
| Worth noting that parts of it are trying to be funny, parts of
| it are plain wrong, and parts of it are dangerously misleading.
| There may be one or two useful bits in it somewheres too.
| ziml77 wrote:
| It may be based in truth, but it's a humor piece.
| andi999 wrote:
| For entertainment? Tone seems a bit over the top sarcastic.
| gallier2 wrote:
| If it is only the tone that bothers you, maybe you should
| abstain from programming C. ;-)
| andi999 wrote:
| First tone then content...
| thayne wrote:
| > Most programs do not need precise control over these sizes;
| many programs that do try to achieve this control would be better
| off if they didn't.
|
| Interesting that modern languages like rust, go, and zig all lean
| towards using integer types with well defined sizes. I think that
| we've learned that the less exact definitions in c can cause
| problems. For example, if you develope and test in an environment
| where int is 32 bits, you could easily end up with bugs that only
| exist if int is 16 bits.
| MaxBarraclough wrote:
| Link to source of quote: http://c-faq.com/decl/exactsizes.html
|
| I'm fond of Ada's approach: generally you just specify the
| range you want and let the compiler figure out the best integer
| size to use. You only need to specify a size if you're doing
| low-level work or FFI.
| addaon wrote:
| Modern C (from C99 onward) introduces a few families of sized
| types -- [u]int[_least|_fast|][8|16|32|64]_t. The non-least-or-
| fast types are not guaranteed to exist (e.g., int8_t is
| optional because implementation may be unreasonable on a 24-bit
| DSP with no sub-word operations), but the _least and _fast
| types are generally what you want anyway, unless you're relying
| on unsigned overflow behavior.
|
| In my experience, modern code is either written almost entirely
| in terms of sized values like int32_t (when assuming a "normal"
| platform), or almost entirely in terms of _least/_fast values
| (when going for maximum portability). The only case that
| "naked" int/long is still common in this model is in a few
| specific uses such as loop indices where it's idiomatic.
|
| The _fast and _least types are especially interesting,
| pragmatically. "int_fast8_t" means "I need a signed value that
| can store values between -128 and 127, doesn't have defined
| behavior on overflow, and is allowed to fill a register / use a
| word worth of memory." "int_least8_t" means "I need a signed
| value that can store values between -128 and 127, doesn't have
| defined behavior on overflow, and I am likely to have a
| significant number of these in memory so please pack them as
| efficiently as reasonable." (And of course we have bit packing
| when we need to pack more efficiently than reasonable; bit-
| packing with int_fast8_t allows you to represent "I need this
| to take exactly 8 bits of memory, whatever it costs compute-
| wise, because I'm basically filling memory with these.")
|
| In general, I find that these types give modern C a good
| balance between declaring requirements on types and not overly
| trying to control their size.
| k__ wrote:
| Nice list, but would be cooler if it was scrollable. One question
| per page is a bit tedious.
| SavantIdiot wrote:
| 1.1. How should I decide which integer type to use?
|
| Programmer: Hmmm, I think these three should be shorts and these
| 10 can fit in chars.
|
| Modern compiler: Fuck that, you're all 32-bits. I ain't got time
| for unaligned memory access...
| sdfdf4434r34r wrote:
| And then you get to the unfortunate situation that is the x64
| ABIs - int is still 32-bit, leading to a bunch of extra movsx
| instructions if you use ints for things like indexing.
| WalterBright wrote:
| Use size_t to declare anything that will be used as an index.
| SavantIdiot wrote:
| This is literally the reason `size_t` was created.
| jstanley wrote:
| Why isn't it called index_t then?
| SAI_Peregrinus wrote:
| Because C doesn't really have indexes, it has pointers
| and offsets. offset_t would make more sense than index_t.
| burnished wrote:
| As a fellow student of "why is this named that, what does
| this name mean" I have found that asking about
| counterfactuals is rarely satisfying. Naming stuff is
| hard and the question assumed a level of intent that I
| think is rarely present. Asking "how did this thing get
| named that" works out better, cause it seems that
| occasionally gets written down.
| jstanley wrote:
| My point was that it seems more likely that size_t was
| created to represent sizes than to represent indexes.
|
| I don't disagree that size_t is an appropriate type _for_
| indexes, but I don 't think indexes are literally the
| reason it was created.
| tialaramex wrote:
| It's named for sizeof, a C operator which returns a
| positive integer but annoyingly the core C language
| itself doesn't define what the type of that integer is,
| the standard library does though, naming it size_t
|
| Now, sizeof does measure the size of things, but, one of
| the obvious sizes you can measure is an array+, and
| that's definitely also the maximum index value for the
| array, so I do think it's fair to say that's (part of)
| literally why size_t exists.
|
| + One of C's treacherous footguns. In the scope where the
| array was defined it's an array, and sizeof(array) tells
| you how big that array is. But, passed as a parameter it
| becomes a _pointer_ and sizeof(resulting_pointer) is the
| size of the pointer, not the array :(
| saagarjha wrote:
| Modern compilers generally prefer register-sized data.
| SavantIdiot wrote:
| Ah thanks, that's what I was thinking. But somehow I got
| caught up in unaligned cacheline accesses, which are much
| larger than 32-bits. It's early where I am. :)
| masklinn wrote:
| I mean there are 4 different concepts at play here:
|
| Unaligned memory access, types generally have an alignment
| which is the same as their length and structs have the
| alignment of their largest member because many
| architectures get quite cross with unaligned access e.g.
| trying to load a 32b integer from memory to register while
| it's not aligned to 32b, this is where compilers will pad
| structures to ensure everything is aligned properly by
| default, and where (in C/C++ anyway) you want to take care
| of your struct layout to avoid unnecessary padding. That
| doesn't prevent "these three should be shorts and these 10
| can fit in chars." at all, but if you intersperse them the
| structure will increase in size due to padding.
|
| Then there's C being specified in terms of lowest
| capabilities so while "char" and "short" are at least 8 and
| at least 16 bits... they can also be larger (POSIX does
| specify that char must be exactly 8 bits but non-POSIX
| platforms don't require that). That matches everything
| being 32b. It's a somewhat common occurrences for DSPs to
| have char of 16 or 32 bits, it really has nothing to do
| with the compiler (except insofar as the compiler does what
| the architecture description specifies).
|
| Then there's the preferred data size, which is probably a
| function of the architectural ALUs than the native
| registers e.g. if an architecture only works on 32b datum
| then computations on 8 bit data will require loading 8
| bits, zeroing the upper 24, performing the computation in
| 32b, copying whichever bit is concerned to the overflow
| flag, then zeroing that. Whereas performing the computation
| on a 32b-native type would require loading 32b, performing
| the computation, done (that was never a concern on x86/64
| but IIRC older revisions of ARM could only natively work in
| 32b, and not all possible arithmetic operations got
| expanded to 8/16b at the same time).
|
| And finally there's the cache line alignment. There are
| actually two opposite issues with cacheline alignments: you
| usually want your structure to not span cachelines (as that
| gets more expensive) but sometimes you want your structures
| be always start at the start of a cacheline (and possibly
| take the entirety of the cacheline) to avoid _false
| sharing_ issues: if two unrelated structures are on the
| same cache line and they 're used from different cores, the
| cores will need a lot more synchronisation than if they
| were on different cache lines.
| logbiscuitswave wrote:
| While I don't particularly like the structure of the FAQ (one
| page per item is definitely tedious to read through - I wish it
| came in a PDF or scrollable form) this is a goldmine of succinct
| and zero frills information. I learned a few things.
| Someone wrote:
| http://c-faq.com/versions.html has downloads for ascii versions
| (that may or may be up to date)
|
| http://www.faqs.org/faqs/C-faq/faq/ has an ascii version from
| July 3, 2004 (again, I wouldn't know whether that is up to
| date, but given its age, it may not be)
| eps wrote:
| Ooooh, this one's good - http://c-faq.com/struct/retcrash.html
| buescher wrote:
| I think I've done that one.
| Doctor_Fegg wrote:
| Newsgroup FAQs are a goldmine. I still find myself referring to
| the comp.graphics.algorithms FAQ repeatedly:
|
| http://www.faqs.org/faqs/graphics/algorithms-faq/
| teddyh wrote:
| Does anyone know what happened to rtfm.mit.edu? It was, quite
| recently, an FTP site where all the Usenet FAQs were archived.
| notorandit wrote:
| Last update in 2005.
| jftuga wrote:
| I love this one:
|
| Why do some people write if(0 == x) instead of if(x == 0)?
|
| http://c-faq.com/style/revtest.html
| bitwize wrote:
| Written by my former colleague Steve Summit, probably the most
| knowledgeable person this side of Dennis Ritchie about
| programming C, especially in Unix environments.
| kdavis wrote:
| A giant among men ;)
___________________________________________________________________
(page generated 2021-09-12 23:00 UTC)