C- Syntax to allocate Global variables to consecutive memory locations

significant

there is no

two major

They're

If you just think about it for more than a second you would realise that if you allocate bitfields the wrong way around you end up with bitfield containers not only being filled from both the least and most significant bits but also from the middle. For example consider the allocation of:

int x :1 char y short z :1 int a : 1 short b : 1 char c : 7

Assuming 32-bit ints and little endian, x will be in bit 31 of the int container, y in bits 0-7, z in bit 15, a in bit 30, b in bit 14 and c in bits 17-23. Now please try to explain this to someone who thinks that assigning bitfields the wrong way around just means the order of bitfields is reversed. It doesn't conform to what most people expect, and thus is wrong.

Wilco

Reply to
Wilco Dijkstra
Loading thread data ...

What's an "int container" supposed to be? The word "container" doesn't appear anywhere in C99.

No matter what the "addressable storage unit" mentioned in the standard is, there's no way such an allocation of bit positions can be justifiable within the rules for element allocation of a struct. For starters, a cannot possibly be in the position you name "bit 30" if z and b are in positions 15 and 14. No matter which way you cut it, that's a direct violation of the "shall be packed into adjacent bits of the same unit" part of paragraph 10 of C99 6.7.2.1.

Why on earth would I want to do that? As opposed to simply telling him to get an actual C compiler rather than try to understand the broken behaviour of the piece of junk he's mistaking for one?

People expect the weirdest shit. It's a mistake to try and follow such expectations.

Reply to
Hans-Bernhard Bröker

Casting integers to pointers is implementation defined. That means you have to check the documentation of your implementation. Many compilers in the embedded world support this. Using a valid integer value (correct alignment, maps onto valid address, ...) will not result in undefined behaviour. It's as simple as that.

Of course, using a wrong integer value is another story. Preventing that is not a matter of 'possibility' but rather of proper design and implementation of the embedded system.

The resulting code may not work for another compiler and/or another platform, but this is c.a.e. isn't it?

Rob

Reply to
Rob Windgassen

I have never seen a C compiler which *did* reorder struct fields, but I thought it was allowed to do so. I guess I was wrong there - thanks for the correction.

Yes, most have some sort of "packed" pragma or attribute. I generally prefer to do padding explicitly (with dummy fields), with a compiler warning if it adds padding itself. As you say, padding, alignment and bit ordering are not a problem when internal to a program - you just have to be careful when the data is being swapped with other programs or targets, or when it is mapped to hardware.

Reply to
David Brown

I think the code is "correct", under certain reasonable assumptions - that the memory exists, is addressable, is writeable in this way, and that the compiler will make the same assumptions.

By the same logic, I would say the following is "correct" C:

extern void bar(char* p); void foo(void) { char buffer[1000]; bar(&buffer[999]); }

There is absolutely nothing in the C standards that guarantees that the platform can allocate 1000 bytes on the stack (or simulated stack) - yet it is still considered correct C because we assume the resources are available.

Thanks for that correction.

Reply to
David Brown

One

does (and

behaviour.

any useful

stop a

*)0x8000. And

_writable_.

of code can

If you can name good technical reasons why it can never work then you would have a point. Just name a few compilers or CPUs where it never works. Arguing that it is not correct when it obviously works for everybody and is used in billions of devices is never going to win any arguments. The C standard is usually 10+ years behind common practise.

memory

make the

You're absolutely right. It does not even matter whether it is unspecified, implementation defined or even undefined behaviour. What matters is that it works. It's a normal expectation to cast between integers and pointers (both are just sets of bits afterall), and it works perfectly fine on all compilers. In the embedded space peripherals are usually accessed by casting integers to pointers.

platform can

considered

Indeed. There are lots of other examples like this.

Wilco

Reply to
Wilco Dijkstra

thought it was

Compilers can reorder fields - if you cannot notice. Since structures are used across multiple sources, it is difficult to prove that you didn't take the address of the fields. However several compilers can change an array of structs into a struct of arrays to improve cache locality, Sun did this on some SPEC code.

Wilco

Reply to
Wilco Dijkstra

anywhere

Bitfield container the compiler term for "addressable storage unit" of a bitfield. You've never worked on a compiler?

there's no

for element

you name

it, that's

unit" part of

int uses a 32-bit container, while short uses a 16-bit one, so these are not the same storage unit and thus your rule doesn't apply.

Anyway how would you allocate these bitfields reversed?

an actual

junk he's

Can you name a compiler that implements reversed bitfields properly according to you? It would be interesting to see how they explain it.

Wilco

Reply to
Wilco Dijkstra

thought it was

Not if they want to be standards compliant.

Which is irrelevent to the standard.

That violates the C standard. The standard says the addresses must be monotonically increasing in the order that they were declared. Period.

It doesn't say you can violate that requirement if the program never uses the address.

--
Grant Edwards                   grante             Yow!  .. Now KEN and BARBIE
                                  at               are PERMANENTLY ADDICTED to
                               visi.com            MIND-ALTERING DRUGS...
Reply to
Grant Edwards

thought it was

Standards compliance only matters for things you can notice. Have you ever used a modern compiler? Many modern compilers split structures into individual fields, allocate some of the fields to registers and remove the unused fields. A field in a register doesn't have an address, let alone a monotonically increasing one...

Are you seriously claiming that these compilers are not compliant?

It's good compiler writers are pragmatic, not pedantic...

If a program that violates the requirement behaves identically to a program that doesn't violate it then it is considered conforming by the C standard (the standard has explicit wording to this effect).

In any case, if you can't tell which one is not conforming then how can it possibly matter? Would you be happy to randomly select one and use it, eventhough it might be not conformant? Or would it make you feel bad somehow? It's a philosophical issue at best.

Wilco

Reply to
Wilco Dijkstra

It is relevant. The standard describes an abstract machine to define the semantics (section 5.1.2.3 of C99). An implementation (compiler) is free to optimize as long as the visible behaviour is not changed:

5.1.2.3 Program execution 1 The semantic descriptions in this International Standard describe the behavior of an abstract machine in which issues of optimization are irrelevant.

....

5 The least requirements on a conforming implementation are:

- At sequence points, volatile objects are stable in the sense that previous accesses are complete and subsequent accesses have not yet occurred.

- At program termination, all data written into files shall be identical to the result that execution of the program according to the abstract semantics would have produced.

- The input and output dynamics of interactive devices shall take place as specified in 7.19.3. The intent of these requirements is that unbuffered or line-buffered output appear as soon as possible, to ensure that prompting messages actually appear prior to a program waiting for input.

Rob

Reply to
Rob Windgassen

I must admit I was wrong. As long as it can be shown that the reordering of fields is not visible, the compiler is allowed to do so. I would maintain that's virtually impossible to do in an embedded system, where things like the location of data in non-volatile memory is "visible" even though it was never "written to a file".

--
Grant Edwards                   grante             Yow! If elected, Zippy
                                  at               pledges to each and every
                               visi.com            American a 55-year-old
                                                   houseboy ...
Reply to
Grant Edwards

But this sort of thing, which is outside of the definition of the C language, might not "count" as visible. That's why a compiler can optimize out a variable used as a semaphore, unless declared volatile, since C knows nothing of threads. So I don't see why a compiler can't re-arrange structure fields, since this could be made invisible within the C language. (But very bad if the structure maps onto a hardware device).

--

John Devereux
Reply to
John Devereux

appear anywhere

We're talking about the language to be compiled, here, not the compilers.

there's no

for element

you name

it, that's

unit" part of

Except that there's no in and no short anywhere in that examples. There are lots of 1-bit bitfields, specified with different base types. You apparently insist on those base types having more relevance to the allowable allocation sequences than the language definition. That's a rather strange point-of-view, but not one I'm going to share.

And by the way, that's not "my" rule, that's what the language definition says.

Assuming 32-bit "units": x in a unit of its own, as its MSBit. y goes into another unit, because it's not a bit-field. z is the MSBit (#31) of another unit, followed by a (bit 30), b (bit 29) and c (bits 28 to

22) --- the unit is large enough, so they have to be adjacent, which leaves no other option once 'y' has been put in the MSBit.
Reply to
Hans-Bernhard Bröker
[...]

That's a delusion. The code is incorrect, precisely *because* you have to make external assumptions to avoid it causing undefined behaviour.

None of those assumptions are part of the code sample in question.

Actually, to some extent there is: C99 5.2.4.1: the 65535-byte object requirement.

Reply to
Hans-Bernhard Bröker

...which is why lots of hideousness exists with #pragma directives and packed attributes.

-p

--
"Unix is user friendly, it's just picky about who its friends are."
 - Anonymous
--------------------------------------------------------------------
Reply to
Paul Gotch

appear

Bitfield container is standard terminology used to describe how to allocate bitfields, for example in compiler documentation. This is relevant because we're talking about implementing the language, not about the standard in a theoretical way.

there's no

for

position

way you cut

the same

lots of

on those

the language

share.

Well this is how bitfield containers work. The base type of a bitfield is used as the container type, ie. it determines the placement and alignment of the bitfield as well as the access type. Containers may overlap, so that bitfields are packed as tightly as possible (which is a key requirement). Whether you agree or not, this is how compilers implement bitfields.

Actually the language is unclear, which is why I developed a consise mathematical definition of bitfields that both adheres to the standard as well as meeting all expectations people have of bitfields. Effectively all fields, whether bitfield or not, are allocated like bitfields. So there is no difference between char x and char y:8 in terms of layout.

another

followed by a

they have to

That's 12 bytes for the structure rather than 4 which is what people expect (and you violate the requirement that bitfields are allocated to a containers of the appropriate type - c straddles 2 8-bit containers - and the requirement that containers are allocated on ascending addresses). The non-reversed version takes 4 bytes on most compilers, try it out on GCC for example.

The problem is that it is impossible to come up with a definition that allows the reversed variant to be the same size as the normal structure and not violate the standard. One way would be to allocate all fields big-endian style (so fields are exactly mirrored), but this means not all fields have increasing addresses.

Wilco

Reply to
Wilco Dijkstra

But this in in the context of an embedded system which does have hardware or memory which can be accessed at that address - that is the whole point of what the OP is trying to do. Of course this code won't work on a different hardware platform, but I don't think this makes the code "incorrect" in the context of embedded systems.

Otherwise any kind of hardware driver written in C is "incorrect", because it inherently has to make assumptions about the hardware behaviour!

--

John Devereux
Reply to
John Devereux

You can ask your low level guy to support. He should know how to assign memory location for your globals.

And you can search the keywords: "#pragma", "section", "segment", "link file", "linker".

good luck.

snipped-for-privacy@gmail.com wrote:

Reply to
dick

Volatile is the standard way for this sort of thing (of course like most other language featues volatile is not very well defined in C, but compiler writers and their users agree on what it means). It forces the compiler to perform all reads and writes as written in the source code, including the exact width the user specified and their order.

Wilco

Reply to
Wilco Dijkstra

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.