Live data from Hacker News

22nd Century C

procedural.github.io

91–100 of 106 posts

Re: 22nd Century C

#91
post #68

Earlier quoted context omitted.

I did not expect you'd say "char", because it's a fixed size numeric type. Isn't that what you have been arguing against so far? Anyway, I'd get yelled at if I checked in code where I do math on char. It has to be on uint8 or int8 (or other widths). Not that I'd ever check in such code, after all, I agree with the company policy there. But "char" is just a part of the problem. We have the same issue with all kinds of…

char isn't fixed width. It is guaranteed to be at least 8-bits wide, but on a SHARC chip it is 32-bits wide. > The thing is, I assume all uintX types to really mean at least X bits wide. I am aware that the compiler is free to use its discretion for allocating memory. I worry about finer details only when I need to. That is explicitly not what they are. The standard is very clear that they must be exactly X bits wide…

This miscommunication was my fault. We don't use uint8_t or other such things, we use uint8, uint16, etc. These are typedefed to compiler-specific types that guarantee a required minimum size. This is also the reason we are not allowed to do arithmetic on chars. The types we use may eventually get typedefed to a char, but at least when I see someone else's function that requires a char as opposed to uint8, I know he's dealing with actual characters.

> then you have to do all the reasoning as if the type is of an unknown width

Well, no. If we are writing portable math routines for such types, it gives us nice ranges for which the code should behave with correct answers or should throw red flags during unit testing.

Re: 22nd Century C

#92
post #91

Earlier quoted context omitted.

char isn't fixed width. It is guaranteed to be at least 8-bits wide, but on a SHARC chip it is 32-bits wide. > The thing is, I assume all uintX types to really mean at least X bits wide. I am aware that the compiler is free to use its discretion for allocating memory. I worry about finer details only when I need to. That is explicitly not what they are. The standard is very clear that they must be exactly X bits wide…

This miscommunication was my fault. We don't use uint8_t or other such things, we use uint8, uint16, etc. These are typedefed to compiler-specific types that guarantee a required minimum size. This is also the reason we are not allowed to do arithmetic on chars. The types we use may eventually get typedefed to a char, but at least when I see someone else's function that requires a char as opposed to uint8, I know he'…

Why not uint_{least,fast}{8,16,32,64}_t ?

Re: 22nd Century C

#93
post #92
post #91

Earlier quoted context omitted.

This miscommunication was my fault. We don't use uint8_t or other such things, we use uint8, uint16, etc. These are typedefed to compiler-specific types that guarantee a required minimum size. This is also the reason we are not allowed to do arithmetic on chars. The types we use may eventually get typedefed to a char, but at least when I see someone else's function that requires a char as opposed to uint8, I know he'…

Why not uint_{least,fast}{8,16,32,64}_t ?

These are good, but some of our codebases predate these conventions. We don't even use // for commenting, because the code could find its way to a compiler that can't handle C99. Secondly, the overriding principle here is that the massive company, despite dealing with a huge variety of architectures, has to speak one language.

If I were to start a company today in a similar domain, and not have a legacy to deal with, I would mandate uint_{least,fast}{8,16,32,64}_t and such.

Re: 22nd Century C

#94
post #91

Earlier quoted context omitted.

char isn't fixed width. It is guaranteed to be at least 8-bits wide, but on a SHARC chip it is 32-bits wide. > The thing is, I assume all uintX types to really mean at least X bits wide. I am aware that the compiler is free to use its discretion for allocating memory. I worry about finer details only when I need to. That is explicitly not what they are. The standard is very clear that they must be exactly X bits wide…

This miscommunication was my fault. We don't use uint8_t or other such things, we use uint8, uint16, etc. These are typedefed to compiler-specific types that guarantee a required minimum size. This is also the reason we are not allowed to do arithmetic on chars. The types we use may eventually get typedefed to a char, but at least when I see someone else's function that requires a char as opposed to uint8, I know he'…

If that is the case, then it sounds like this whole thread has been miscommunication :-)

The very start of this was talking about how fixed width types are not particularly helpful. I was under the impression that you were making the case for fixed width types, but it sounds like we've all been on the same side the whole time.

> Well, no. If we are writing portable math routines for such types, it gives us nice ranges for which the code should behave with correct answers or should throw red flags during unit testing.

Exactly - if you are writing portable maths routines for your int16 type (i.e. a type which is at least 16-bits wide), then you do the analysis as if the type is exactly 16-bits wide. However, it might be that the type is actually 32-bits wide, and that doesn't change things.

Re: 22nd Century C

#95

Earlier quoted context omitted.

> Honestly, there's no way I'd use an MCU that doesn't support 16-bit integer types. I've never even heard of such a thing. SHARC chips don't have any integer types smaller than 32-bits. Why would they, when they can't address any smaller than 32-bits? > I've also never heard of a 24-bit processor -- unless you're thinking of some antediluvian bit-slice processor, or something like that? 56k chips have 24-bit chars.…

SHARC chips don't have any integer types smaller than 32-bits. 56k chips have 24-bit chars. Not so common any more, but they are still kind of kicking around. Well, those chips are DSPs, which is kind of a different horse. Why would they, when they can't address any smaller than 32-bits? How, for instance, would you write a TCP/IP stack, if you can't do something like this? struct tcp_hdr { PACK_STRUCT_FIELD(u16_t sr…

> Well, those chips are DSPs, which is kind of a different horse.

This whole discussion has been about portable code. The point is that no matter what the horse is, you can still write code that works (and works efficiently).

If you are writing a portable TCP/IP stack, then having a struct like you described doesn't help you one bit. It looks like you are setting things up so you can directly blat the bits into it (or avoid the copy and interpret some bits using this struct, whatever). If you do this, then you don't have portable code because of endianness.

To make this code portable, you separate the in memory representation from the "on-wire" representation. The memory representation doesn't need compiler specific things like PACK_STRUCT_FIELD would expand to, it only needs types that are at least 16 or 32 bits wide. The code that fills in the struct needs to operate byte at a time and then fill in the struct members appropriately.

Note that because byte in C isn't necessarily 8-bits wide, you have to be a little bit careful with the "byte-at-a-time" code, but it is very possible to write it so it works on any whacky machine that has a C compiler - including DSPs... they really aren't that special.

Re: 22nd Century C

#96
post #91

Earlier quoted context omitted.

This miscommunication was my fault. We don't use uint8_t or other such things, we use uint8, uint16, etc. These are typedefed to compiler-specific types that guarantee a required minimum size. This is also the reason we are not allowed to do arithmetic on chars. The types we use may eventually get typedefed to a char, but at least when I see someone else's function that requires a char as opposed to uint8, I know he'…

If that is the case, then it sounds like this whole thread has been miscommunication :-) The very start of this was talking about how fixed width types are not particularly helpful. I was under the impression that you were making the case for fixed width types, but it sounds like we've all been on the same side the whole time. > Well, no. If we are writing portable math routines for such types, it gives us nice range…

> If that is the case, then it sounds like this whole thread has been miscommunication :-)

I am not sure about that. The original poster wrote 'I have never once thought: "You know what, I'd like to make a decision as to the width of an integer every time I declare a function."' I disagreed with that, and that's where the whole discussion started off. And I still advocate using the smallest (explicitly sized) type you could get away with. Weren't you advocating using bare C types (unsigned char, short, long, etc.) for your variables all along?

Re: 22nd Century C

#97

Earlier quoted context omitted.

SHARC chips don't have any integer types smaller than 32-bits. 56k chips have 24-bit chars. Not so common any more, but they are still kind of kicking around. Well, those chips are DSPs, which is kind of a different horse. Why would they, when they can't address any smaller than 32-bits? How, for instance, would you write a TCP/IP stack, if you can't do something like this? struct tcp_hdr { PACK_STRUCT_FIELD(u16_t sr…

> Well, those chips are DSPs, which is kind of a different horse. This whole discussion has been about portable code. The point is that no matter what the horse is, you can still write code that works (and works efficiently). If you are writing a portable TCP/IP stack, then having a struct like you described doesn't help you one bit. It looks like you are setting things up so you can directly blat the bits into it (o…

I think we have to decide whether we're talking about specialized and/or archaic technological artifacts or modern general-purpose processors. My interest is limited to the latter, all of which have C compilers that support 1, 2, 4, and 8-element wide integers composed of 8-bit bytes. Confining the notion of "portability" to these platforms is fine with me. I'll definitely have to yield the point with respect to older DSP chips; I've never written code for a 56K or a SHARC, and never will.

Endianness is generally hidden with wrapper macros or functions, and I suppose you could do the same to pretend you're accessing integers of unsupported sizes. But you can rest assured that losing track of the sizes of the underlying types is going to bite you in the ass. If I can't use typedefs, I'll want to use some semantically-equivalent notational cues.

Re: 22nd Century C

#98
post #96

Earlier quoted context omitted.

If that is the case, then it sounds like this whole thread has been miscommunication :-) The very start of this was talking about how fixed width types are not particularly helpful. I was under the impression that you were making the case for fixed width types, but it sounds like we've all been on the same side the whole time. > Well, no. If we are writing portable math routines for such types, it gives us nice range…

> If that is the case, then it sounds like this whole thread has been miscommunication :-) I am not sure about that. The original poster wrote 'I have never once thought: "You know what, I'd like to make a decision as to the width of an integer every time I declare a function."' I disagreed with that, and that's where the whole discussion started off. And I still advocate using the smallest (explicitly sized) type yo…

> I am not sure about that. The original poster wrote 'I have never once thought: "You know what, I'd like to make a decision as to the width of an integer every time I declare a function."' I disagreed with that, and that's where the whole discussion started off.

But your solution also doesn't involve deciding on the width of an integer - your solution is to use integers that have a minimum width. By doing that, you are saying that you don't care about the width of an integer, as long as it is at least N bits, which is exactly the right thing to do for portable code.

> And I still advocate using the smallest (explicitly sized) type you could get away with.

This is where I'm a little confused, if we go back:

>> Would you suggest a uint29_t?

> If you are aware of a machine that provides that, yes! Otherwise, I'd suggest uint32_t. Yes,

If I understand what you are saying, then you are saying that at your work you use "intN" to mean "an integer of at least N bits". Every machine that has a C compiler for it has such a type - one possible type that could satisfy this is long. If you have a C99 compiler, then another type is int_least32_t.

So from this, it sounded like you were talking about fixed width types.

> Weren't you advocating using bare C types (unsigned char, short, long, etc.) for your variables all along?

I've been advocating for non-fixed width types all along. How their names are spelt is a secondary thing and one where lots of people have different opinions which makes it hard to be black and white. However, the meanings of the words is what I care about, and so whenever I gave examples I would tend towards the C90 types because they have the right semantics (they are minimum width types of sensible sizes) and they are portable everywhere (how long has it taken for MS to have stdint.h in their C compiler?) and have definitions that can be expected to be known by any C programmer (since their definitions are part of the language definition of C).

Personally, I think that the int_leastN_t types are ugly, so I avoid them (and it sounds like your company does too, since it renames them to less ugly (but I think more confusing) names). Although they are ugly, I do think their semantics are good enough to use for portable code. I wouldn't say the same about the fixed width types (since they may not exist) or the "fast" types (they aren't good for portability because their size is ambiguous across toolchains targeting the same ABI - compare the GNU definitions to the MSVS definitions). This paragraph is just my opinions, and I expect others to have differing opinions, and I don't really care. What I will hold to though is that fixed width types are bad for portability, and I think you agree with that.

Re: 22nd Century C

#99

Earlier quoted context omitted.

> Well, those chips are DSPs, which is kind of a different horse. This whole discussion has been about portable code. The point is that no matter what the horse is, you can still write code that works (and works efficiently). If you are writing a portable TCP/IP stack, then having a struct like you described doesn't help you one bit. It looks like you are setting things up so you can directly blat the bits into it (o…

I think we have to decide whether we're talking about specialized and/or archaic technological artifacts or modern general-purpose processors. My interest is limited to the latter, all of which have C compilers that support 1, 2, 4, and 8-element wide integers composed of 8-bit bytes. Confining the notion of "portability" to these platforms is fine with me. I'll definitely have to yield the point with respect to olde…

You seem to think that it is difficult to write programs with this level of portability. It really isn't, you just program to the language spec, and everything else falls out. You don't need to come up with arbitrary rules about which processors are too specialized or archaic. The alternative you provide isn't obviously better than just writing portable code, but from what I can tell, you have never actually just tried the alternative.

I can assure you that knowing that exact width of types is rarely useful when writing super portable code for platforms that are different enough that you are happy to decide that you wouldn't even bother coding for them. So I'm puzzled by why it suddenly becomes helpful when you decide you are only going to look at a subset of those platforms.

Give an example of how it is going to bite me in the ass and then the discussion can be less emotional and actually based on facts.

Re: 22nd Century C

#100
post #96

Earlier quoted context omitted.

> If that is the case, then it sounds like this whole thread has been miscommunication :-) I am not sure about that. The original poster wrote 'I have never once thought: "You know what, I'd like to make a decision as to the width of an integer every time I declare a function."' I disagreed with that, and that's where the whole discussion started off. And I still advocate using the smallest (explicitly sized) type yo…

> I am not sure about that. The original poster wrote 'I have never once thought: "You know what, I'd like to make a decision as to the width of an integer every time I declare a function."' I disagreed with that, and that's where the whole discussion started off. But your solution also doesn't involve deciding on the width of an integer - your solution is to use integers that have a minimum width. By doing that, you…

> But your solution also doesn't involve deciding on the width of an integer - your solution is to use integers that have a minimum width.

We declare the minimum width for all variables. We don't use "int" in for loops and hope for the best. I wouldn't go as far as to say "we don't care". We don't worry too much for code that's mean to be portable. We obviously care in non-portable code. But the important point here is that we use the same conventions whether we are writing portable code or not.

> So from this, it sounded like you were talking about fixed width types.

C99 conventions are too radically new to be used across our entire codebase. Uglyness has nothing to do with it. The only way to ensure fixed widths without int_leastX conventions is to be intimately familiar with the platform while we are declaring our typedefs, or creating makefiles for our projects. And to that extent, we use only fixed with types.

Post reply on HN