- sizeof(bitfield struct) - 13 Updates
- What does operating on raw bytes mean in a C++ context? - 6 Updates
- Module libraries - 3 Updates
- spurious warning? - 1 Update
- Good random number generators version 1.0, you can port it to C++ - 1 Update
- spurious warning? - 1 Update
Keith Thompson <kst-u@mib.org>: Nov 05 06:00PM -0800 David Brown <david.brown@hesbynett.no> writes: [...] > bits are unused - but they still take up space in the struct, and still > affect alignment. > If you want this all to be within a 16-bit struct, use u16 (or uint16_t). [...] > The size (and alignment) comes from the size of the underlying type, > which is 32-bit in this case. The standard says that allocation of bit-fields is implementation-defined. I don't see anything in the standard that implies either that there is, or that there isn't, any difference between, for example, int8_t bitfield : 5; and int32_t bitfield : 5; though I think some ABIs impose more specific requirements. -- Keith Thompson (The_Other_Keith) kst@mib.org <http://www.ghoti.net/~kst> Will write code for food. "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Nov 05 06:53PM -0800 On Monday, November 5, 2018 at 9:00:18 PM UTC-5, Keith Thompson wrote: > int8_t bitfield : 5; > and > int32_t bitfield : 5; +1. > though I think some ABIs impose more specific requirements. They'd have no choice, but to compute the two examples above for sizeof() to be int8_t = 1 and int32_t = 4 is just wrong on every level. -- Rick C. Hodgin |
David Brown <david.brown@hesbynett.no>: Nov 06 10:49AM +0100 On 06/11/18 03:00, Keith Thompson wrote: > and > int32_t bitfield : 5; > though I think some ABIs impose more specific requirements. Certainly it is common for ABI's (or compiler implementations) to use the declared underlying type for allocation sizes and alignments. It is also common in embedded systems (where bitfields and volatile are common) to insist that the compiler respects the access size when dealing with volatile structs with bitfields. But as for the standards, I don't see it clearly expressed - so it does not seem to be a requirement. It talks about "the addressable storage unit holding the bit-field", and C11 6.7.2.1 describes how packing of bits within these units is to be done (with plenty of room for implementation defined behaviour). There does not appear to be anything saying that the "addressable storage unit" here has to be of the size and type of the bit-field's type - indeed, "An implementation may allocate any addressable storage unit large enough to hold a bit-field". However, the usefulness of bit-fields for "conforming to externally imposed layouts" would be hindered if the implementation did not give the programmer control over the sizes here. Older C compilers sometimes had support for only "signed int" and "unsigned int" as bit-field types - most that I have used in the past couple of decades have supported a range of types. It is certainly possible that compilers with only "int" and "unsigned int" as types would have used smaller underlying storage units, while I think more modern ones use the type you ask for. But it is, naturally, implementation-dependent. (I have looked through the C++ standards too, and didn't see any difference here.) |
David Brown <david.brown@hesbynett.no>: Nov 06 10:57AM +0100 On 06/11/18 03:53, Rick C. Hodgin wrote: >> and >> int32_t bitfield : 5; > +1. It looks like the standards don't impose rules here, but ABI's and implementations do. > They'd have no choice, but to compute the two examples above > for sizeof() to be int8_t = 1 and int32_t = 4 is just wrong > on every level. No, it is certainly not wrong according to the C (or C++) standards, nor is it wrong according to the ABI's of many processors and C implementations. And speaking as someone who uses bitfields regularly in cases where exact layouts and accesses are important, it is often /essential/ that the type of the bitfield be used for the size, alignment and accesses. It is extremely simple to get the layout you want - use an appropriately sized underlying type. (Yes, support for that is implementation-dependant - but so are most things regarding bit-fields.) |
"Öö Tiib" <ootiib@hot.ee>: Nov 06 03:08AM -0800 On Tuesday, 6 November 2018 11:57:41 UTC+2, David Brown wrote: > It is extremely simple to get the layout you want - use an appropriately > sized underlying type. (Yes, support for that is > implementation-dependant - but so are most things regarding bit-fields.) When it is "extremely simple" (just implementation dependent) then there must be is a standard compliant way to static assert that we got the layout that we wanted. Is there such a way? |
David Brown <david.brown@hesbynett.no>: Nov 06 12:17PM +0100 On 06/11/18 12:08, Öö Tiib wrote: > When it is "extremely simple" (just implementation dependent) then there > must be is a standard compliant way to static assert that we got the layout > that we wanted. Is there such a way? Lots of things in C and C++ sound extremely simple, and are extremely simple to describe - yet turn out to be really hard with nothing but standard compliant code! Here I'd say a static assert on the sizeof the struct was the best you can do - that would likely fail if you've made incorrect assumptions about the layout. But it won't cover everything, and it certainly won't cover the order of the bit-fields. |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Nov 06 04:43AM -0800 On Tuesday, November 6, 2018 at 4:57:41 AM UTC-5, David Brown wrote: > It is extremely simple to get the layout you want - use an appropriately > sized underlying type. (Yes, support for that is > implementation-dependant - but so are most things regarding bit-fields.) Have you ever seen the movie [Ice Station Zebra]? In my best Russian accent: "And now I must tell you how wrong you are." The bit expression is a bit expression. And, if you truly need something like Ian's 13-bit packed data structs, use interleaving structs which begin at byte boundaries and ignore the previous portions from prior structs. But the sizeof() a bit packed struct should be rounded to the nearest larger byte. The expressed type of those bits should not affect in any way the sizeof() operation. It should always report its byte size occupancy as rounded up to the nearest byte. Only when I use sizeof(bitstruct.member) should it report the sizeof() that type. It's just flatly wrong... and now I have to support this failure in philosophy in CAlive for compatibility. To quote C3PO: "Oooh. How horrid." -- Frederick Clarkson Hodgin, III PS - Bonus points if you can figure out how they got "Rick" from that. |
Juha Nieminen <nospam@thanks.invalid>: Nov 06 01:37PM > When it is "extremely simple" (just implementation dependent) then there > must be is a standard compliant way to static assert that we got the layout > that we wanted. Is there such a way? There aren't always ways to static_assert such things. For example, there is no standard-compliant way to static_assert that we are compiling for a little-endian system, for instance. (This might be on purpose.) |
"Öö Tiib" <ootiib@hot.ee>: Nov 06 06:01AM -0800 On Tuesday, 6 November 2018 15:38:02 UTC+2, Juha Nieminen wrote: > For example, there is no standard-compliant way to static_assert that > we are compiling for a little-endian system, for instance. (This might > be on purpose.) I really can't imagine purpose. For example: | C99 6.4.4.4p10: "The value of an integer character constant containing | more than one character (e.g., 'ab'), or containing a character or escape | sequence that does not map to a single-byte execution character, is | implementation-defined." Why? Who benefits from such a wasted feature? That could be defined to follow order of bytes on platform. |
David Brown <david.brown@hesbynett.no>: Nov 06 03:02PM +0100 On 06/11/18 13:43, Rick C. Hodgin wrote: > which begin at byte boundaries and ignore the previous portions > from prior structs. But the sizeof() a bit packed struct should > be rounded to the nearest larger byte. You write that as though it was some sort of indisputable fact. It is not fact, and it is not indisputable - it is nothing more than your idea of what you think would be best. It is, of course, fine to have your opinion - but realise that it is /your/ opinion, and it does not appear to match the opinion of people making or using C compilers. In particular, the idea that there is one fixed "right" way to do things here simply has no anchoring in reality. If you want to use bit-fields, you need to be very careful to check the layout matches what you want. Don't assume anything, don't assume consistency between systems. And test rigorously. Some ABIs will define the bit-field layout exactly - some compilers may not follow these ABIs exactly. Compilers can have options that affect the layout, and can have extensions ("packed" attributes or pragmas) that affect them. From a bit of experimenting on godbolt.org, I only found one compiler for which this struct was not the same size as "int" : struct A { int x : 1; int y : 2; } That was the AVR, which is an 8-bit microcontroller, where you usually want to save ram. It used one byte for A. (The AVR is also the only compiler here where the alignment of "int" is less than its size. Being 8-bit, there are no benefits in having larger alignments for any type.) The msp430 compiler, being a 16-bit device, used 2 bytes. All the rest used 4. > The expressed type of those bits should not affect in any way the > sizeof() operation. It should always report its byte size occupancy > as rounded up to the nearest byte. Again, that is an assertion without justification and without foundation in reality. That is, quite simply, not the case in practice. > Only when I use sizeof(bitstruct.member) should it report the sizeof() > that type. That is not allowed at all in C or C++. (It would not be unreasonable to have some sort of "bitsizeof" operator here, but it does not exist in C or C++.) > It's just flatly wrong... and now I have to support this failure > in philosophy in CAlive for compatibility. I think you overrate your opinions. Does it never occur to you that when other tools handle something differently, it is /you/ that is wrong? Alternatively, perhaps it simply doesn't matter that much - people manage to get what they need? We are not talking about a complicated or unintuitive workaround here - you want everything to fit in a 16-bit struct, so use 16-bit types instead of 32-bit types. What you can be sure of, is that however you implement things in your own language, it will be in conflict with the way bit-fields work with some compilers. |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Nov 06 06:08AM -0800 On Tuesday, November 6, 2018 at 9:02:38 AM UTC-5, David Brown wrote: > > But the sizeof() a bit packed struct should > > be rounded to the nearest larger byte. > You write that as though it was some sort of indisputable fact. It is. > > sizeof() operation. It should always report its byte size occupancy > > as rounded up to the nearest byte. > Again, that is an assertion... Again, it is. And I'm amazed to find so many compiler authors doing it wrong. Bitfield structs require some special attention. The question exists in how can I inquire at runtime the sizeof() the bits in the bitfield, compared to the sizeof() the type it represents, compared to the sizeof() the entire bitfield struct, compared to the size of the entire structure expanded to its expressed types. I think bitfield structs are not yet completely cooked in the existing compilers. Just enough to get it close, but they didn't bring it to a close. -- Rick C. Hodgin |
David Brown <david.brown@hesbynett.no>: Nov 06 03:40PM +0100 On 06/11/18 15:08, Rick C. Hodgin wrote: >>> be rounded to the nearest larger byte. >> You write that as though it was some sort of indisputable fact. > It is. This is like arguing with a wall. Look, your opinion does not match that of compiler writers, ABI designers, language designers or programmers. These folks have come to different conclusions about the best way to implement bit-fields - not always to the same conclusions, but often different from yours. You are not smarter than these folks. You are not able to see something that they are missing. You are not able to divine some sort of "fundamental" issue to which they are blind. You are simply a developer with an opinion (which is fine), and an over-inflated sense of the value of that opinion (which is not fine). > in the bitfield, compared to the sizeof() the type it represents, > compared to the sizeof() the entire bitfield struct, compared to > the size of the entire structure expanded to its expressed types. You can't - not with standard C or C++, and not with any existing extensions I am aware of. People have programmed in C for 40 years without such features, so I don't think the need of them is particularly pressing. But if you feel they would be useful, put them into your own language. (I have often felt that a bit more introspection capabilities in C and C++ would be nice, though I have never felt the need of it for bit-fields.) (There is a proposal for adding introspection to C++, but that is going to be a much bigger feature.) > I think bitfield structs are not yet completely cooked in the > existing compilers. Just enough to get it close, but they didn't > bring it to a close. Bit-fields certainly have their limitations, and their loose implementation-defined nature makes them difficult for portability. With appropriate care, they have their place in programming, and many people use them. But when designing a new language with different requirements than C, it may make sense to create an alternative with much stricter rules. |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Nov 06 06:49AM -0800 On Tuesday, November 6, 2018 at 9:40:30 AM UTC-5, David Brown wrote: > You can't - not with standard C or C++, and not with any existing > extensions I am aware of. People have programmed in C for 40 years > without such features... An oversight by all to be sure. They're not pressing, but you can't even obtain that information in today's compilers. It is most definitely an oversight. You say talking to me is like talking to a wall? I just happen to know I'm right. And today I've added bounce structs to CAlive to allow reflection mirrors of the bitfield types into their native types, and back again. I'll also allow the sizeof() to return the size in bytes, and the bitsizeof() to return the size in bits, and that will be globally, not just on bitfield structs or members. Good day, David. -- Rick C. Hodgin |
Juha Nieminen <nospam@thanks.invalid>: Nov 06 07:13AM >>anymore? > Yes. The Unisys clearpath dorado systems decended from the Sperry/Univac 1100 > come to mind immediately. Does it even have a modern C++ compiler? Does anybody even know how to use such a thing? |
David Brown <david.brown@hesbynett.no>: Nov 06 10:19AM +0100 On 05/11/18 21:21, Juha Nieminen wrote: >> Are you sure that CHAR_BIT, the number of bits per byte, equals 8? > Does any computer system where CHAR_BIT isn't 8 even running > anymore? There are three kinds of systems that have CHAR_BIT > 8 : 1. Dinosaur mainframes. There are not many of these still in action, but they do exist. I don't know if there is much C++ on such systems - COBOL is more likely. 2. Very niche processors and DSP's with very odd byte sizes. If you are not in the business of custom ASIC systems, you will never come across them - and your code will never be used on them. Even in the embedded world, these things are unusual. You'll be using a specialised C compiler or assembly, not C++. 3. General purpose DSP's with 16-bit or 32-bit char, like TI TMS320F2xxx or Analog Devices SHARC. I believe some of these can be programmed in C++ these days, but they have fallen out of style for anything but specialised DSP applications like audio or video codecs. I think it is fair to say that if your code would ever be running on something that has CHAR_BIT not equal to 8, you would know it. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 06 12:27PM +0100 On 05.11.2018 21:21, Juha Nieminen wrote: >> Are you sure that CHAR_BIT, the number of bits per byte, equals 8? > Does any computer system where CHAR_BIT isn't 8 even running > anymore? Embedded computing stuff. E.g. Texas Instruments digital signal processors. Cheers!, - Alf |
Juha Nieminen <nospam@thanks.invalid>: Nov 06 01:33PM > I think it is fair to say that if your code would ever be running on > something that has CHAR_BIT not equal to 8, you would know it. That being said, the way I presented the solution would still work even if CHAR_BIT is larger than 8. (Every element of the vector is handled as it if were 8 bits in size, but there's nothing that would break if it were larger.) It would only malfunction if CHAR_BIT is less than 8. The assumption I made in the solution I presented is that chars are *at least* 8 bits in size. |
scott@slp53.sl.home (Scott Lurndal): Nov 06 02:01PM >> come to mind immediately. >Does it even have a modern C++ compiler? Does anybody even know how to use >such a thing? 1) Unknown, but unlikely. Does have a C compiler IIRC. 2) Yes, of course. They're still running production for many large companies (including airline reservation systems). |
David Brown <david.brown@hesbynett.no>: Nov 06 03:03PM +0100 On 06/11/18 14:33, Juha Nieminen wrote: > It would only malfunction if CHAR_BIT is less than 8. The assumption > I made in the solution I presented is that chars are *at least* 8 bits > in size. I hadn't actually read that bit of the thread! CHAR_BIT is /always/ at least 8, so you are safe there. |
Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo>: Nov 06 01:31AM -0500 Thiago Adams wrote: >> https://stackoverflow.com/questions/15773282/access-ident-information-in-an-executable > I don't think it a good idea to increase the size to keep > this information. From my practice, I don't recall when that one string per source file created any size issues (the overhead is usually less than 1-2%). Your mileage can vary, of course. A good thing it gives you a certainty that a particular binary is built from particular set of sources; without injecting a string to the binary, this cannot be done (you might be able to inject something to debug sections, then strip these off though; but this is not what #ident / #scsi do). > pragma once span is to reuse the parsed header in more than > one source file. It will take in account the macros for the > first inclusion and after that it will not be expanded anymore. Are you going to actually compile this file or just pre-process?. If the latter, you probably don't need new pragmas; in fact, you don't even need the pre-processing result's to be a valid C/C++ file. You could just have something like #ifdef WIN32 ..\Scr\ConsoleWin.c #elif defined(linux) ..\Scr\ConsoleLinux.c
Subscribe to:
Post Comments (Atom)
|
No comments:
Post a Comment