4 ms·
C supports systems with segmented memory (https://en.m.wikipedia.org/wiki/Memory_segmentation https://en.m.wikipedia.org/wiki/Memory_segmentation). You also are
by cornstalks 3y ago
C supports systems with segmented memory (https://en.m.wikipedia.org/wiki/Memory_segmentation https://en.m.wikipedia.org/wiki/Memory_segmentation). You also aren’t allowed to observe (or even create pointers which aren’t even dereferenced) memory or addresses outside of allocations you’ve made, so you really can’t observe much about the memory model.
But I think the OP’s point is more about how when you allocate memory, you get an array of bytes to play with. And all higher level languages build on top of that and abstract it away as much as they can.
- AnimalMuppet 3y agoDefine "allowed". Will I get arrested? No. Will the compiler stop me? Also no. Will the program crash? Maybe. Almost certainly if I do it often, or without understanding. You aren't guaranteed to be safe if you access memory or addresses outside of allocations you've made (with stack and static memory counting as "allocations you've made). But on embedded systems with memory-mapped I/O, I have done things like *(unsigned long *)0xFFFE1404 = 0x00011472; in order to write values to the registers of a peripheral device. Those I/O registers were memory that I "owned", even though I never allocated it in any way.
- cornstalks 3y agoThe C standard does not allow it. It’s simply undefined behavior under the standard, and all bets are off as far as C is concerned. But of course an implementation is free to define additional behaviors beyond the C specification. That’s done all the time. But that’s really a “flavor” of C and not pure “vanilla” C.
- trealira 3y agoNo, it's implementation-defined, not undefined behavior. That means the compiler must document a consistent behaviour. From 6.3.2.3 [ISO/IEC 9899:2011]: An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation. Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type. Also, the C standard merely codified existing practices and common extensions. Actual use of C has converted integers to pointers for a long time. If converting integer literals into pointers were undefined behavior, it would just show that the C standard isn't being practically useful in one area (since it's commonly done in practice).
- AnimalMuppet 3y ago> Actual use of C has converted integers to pointers for a long time. Quite probably since the first C-based implementation of Unix on a PDP-11. So it's been known to be "a thing that C does" for quite a bit longer than the standard existed.
- xigoi 3y agoIf you want your program to work on more than one architecture+compiler combination, then implementation-defined is effectively the same as undefined.
- AnimalMuppet 3y agoNot entirely. Say I'm doing my original example, working on an embedded system. My code isn't going to port to anything that doesn't have the same hardware, so architecture isn't an issue. Any compiler supporting that architecture for an embedded application is going to do the right thing with that kind of C statement, so that isn't an issue either. So, implementation-defined means that you can't count on compilers doing the same thing. But there are some things that are implementation-defined where you can pretty much count on any compiler doing the same thing. And, as trealira said, compilers are supposed to clearly state what they do in such cases, so you can read the compiler's statement and see if there are any surprises. This is less true if you're writing library code. There, you have to support all compilers, or at least all conforming ones, and you have to make fewer assumptions.
- trealira 3y agoYou probably know this, but on C compilers targeting the 16-bit x86 CPUs, which have segmented memory, you have near and far pointers to accurately reflect its memory model. Near pointers are 16-bit offsets into the current segment, whereas far pointers consist of a 16-bit segment selector and a 16-bit offset. https://en.wikipedia.org/wiki/Far_pointer https://en.wikipedia.org/wiki/Far_pointer https://en.wikipedia.org/wiki/X86_memory_models https://en.wikipedia.org/wiki/X86_memory_models However, this is not standard C.