Path: csiph.com!weretis.net!feeder6.news.weretis.net!feeder7.news.weretis.net!eternal-september.org!feeder.eternal-september.org!reader01.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c++ Subject: Re: [QT creator on "nix"] - getting a strict 8 bit (1 byte) array with no padding Date: Sat, 23 Nov 2019 12:27:08 -0800 Organization: None to speak of Lines: 137 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="dfad491d1778b0c95e43bf538d0f4f21"; logging-data="609"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/A9rsr3AXLDIwNz/WCX9No" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) Cancel-Lock: sha1:9pMBmJc5sdOWnFKPHMYyb8tbne8= sha1:SSY8X2VDwQ21W8S601dIFwtf++s= Xref: csiph.com comp.lang.c++:70018 Soviet_Mario writes: > Il 23/11/19 07:04, Keith Thompson ha scritto: >> Soviet_Mario writes: >> [...] >>> let's say it explicitely >>> >>> if I have >>> union >>> { >>> struct >>> { >>> u_int_8 Red, Green, Blue, Alpha; >>> }; >>> u_int_32 AllChannels; >>> }; >>> >>> without PRAGMA, do I have any explicit or implicit warranty >>> that my union be 32 bit long ? If so, PRAGMA is useless. If >>> not, it seems it might be useful. >> >> Fixing the spelling of uintN_t (n=8,32) and adding a tag to the union so >> you can use it to define objects: > > again ... > Keith, I did not edit the header manually, and sized ints > HERE are spelled as I wrote. [SNIP] > as you can see the types are spelled as I wrote them, and a > search for uintXX_t does not find anything I didn't know where the names u_int_8 and u_int_32 came from, and assumed they were misspellings of uint8_t and uint32_t. On my own system, #include introduces the non-standard type names u_int{8,32}_t. It doesn't introduce u_int_{8,32}, and I don't see that name in the code you quoted (other than in your union definition) or anywhere under /usr/include on my system. On the other hand, the types uint8_t and uint32_t are defined by the C and C++ standards (starting with C99 and C++11, respectively). Nobody is suggesting that you're lying or manually editing headers. All we're saying is that uint8_t and uint32_t are the *standard* types that meet your requirements, and there is no good reason to use non-standard types with similar names. Do you have some reason to prefer to use u_int_8 rather than uint8_t? > is this that big problem ? > I guess the variations stands for the same concept Yes. Names other than uint8_t are non-standard and will cause your code not to compile in many environments. >> union u { >> struct { >> uint8_t Red, Green, Blue, Alpha; >> }; >> uint32_t AllChannels; >> }; >> >> (You have an anonymous struct, which is standard but wasn't added until >> C11, so older compilers might not support it, or might not support it >> by default.) > > it gives me warnings indeed, but seems to compile nevertheless What warnings? If you compile with "gcc -std=c11" or with a sufficiently new version of gcc, there shouldn't be any. Always pay attention to warnings. [...] >> It's very very likely that the struct and the union will both be >> exactly 32 bits. A compiler is not prohibited from adding padding >> between members or after the last one, > > and that was the reason why I had thought of trying to give > it a strong hint not to pad by mean of a #pragma pack directive If it works without a non-standard #pragma pack, why would you add it? You risk your code failing to compile, or compiling incorrectly, with an implementation that doesn't support #pragma pack or that does something unexpected. >> but there's unlikely to be >> any good reason to do so in this case. The most likely way this >> could fail is if a compiler insisted on making the structure 64 bits. > > so either it packs natively, either it listens to my > explicit hint, either it ignore the #pragma and does not pack. > > Does the #pragma directive increase, decrease, not affect > the likelyhood of packing ? That was the reasoning behind my > approach > > I thought : I give you an hint : TRY to pack. If you really > cannot, there is nothing else I could do There's no guarantee that all compilers will understand your "hint", and nothing in the standard that says anything at all about what "#pragma pack" does. [...] >> There is *no* guarantee about which of the four uint8_t members >> correspond to which part of AllChannels. > > and I don't need such warranty : I use AllChannels only for > mass-copying, assignments, copy constructor. When I need > access to separate channels I use named members. What operations do you need on AllChannels that you can't perforom on the struct? You can assign structs. [...] >> Attempting to use #pragma pack is very likely to do nothing *at best*. > > well ... until now, I am thinking it is likely to do nothing > *at worst* as no one has explained which drawbacks it were > supposed to be in the particular case (I'm not referring to > other more general examples with longer integers > hypothetically spanning non multiple addresses : here I have > 1 byte sizes, and the only big member starts at 0 offset) The drawback of #pragma pack is that it's non-standard. Given the concern you've expressed about portability, I would think that would be important to you. And given that it will almost certainly do nothing, I don't know why you're so insistent on using it. -- Keith Thompson (The_Other_Keith) kst-u@mib.org Working, but not speaking, for Philips Healthcare void Void(void) { Void(); } /* The recursive call of the void */