How does the OS know how much to increment different pointers?
With a 32-bit OS, we know that the pointer size is 4 bytes, so sizeof(char*)
is 4 and sizeof(int*)
is 4, etc. We also know that when you increment a char*
, the byte address (offset) changes by sizeof(char)
; when you increment an int*
, the byte address changes by sizeof(int)
.
My question is:
- How does the OS know how much to increment th开发者_如何转开发e byte address for
sizeof(YourType)
?
The compiler only knows how to increment a pointer of type YourType *
if it knows the size of YourType
, which is the case if and only if the complete definition of YourType
is known to the compiler at this point.
For example, if we have:
struct YourType *a;
struct YourOtherType *b;
struct YourType {
int x;
char y;
};
Then you are allowed to do this:
a++;
but you are not allowed to do this:
b++;
..since struct YourType
is a complete type, but struct YourOtherType
is an incomplete type.
The error given by gcc
for the line b++;
is:
error: arithmetic on pointer to an incomplete type
The OS doesn't really have anything to do with that - it's the compiler's job (as @zneak mentioned).
The compiler knows because it just compiled that struct or class - the size is, in the struct case, pretty much the sum of the sizes of all the struct's contents.
It is primarily an issue for the C (or C++) compiler, and not primarily an issue for the OS per se.
The compiler knows its alignment rules for the basic types, and applies those rules to any type you create. It can therefore establish the alignment requirement and size of YourType
, and it will ensure that it increments any YourType*
variable by the correct value. The alignment rules vary by hardware (CPU), and the compiler is responsible for knowing which rules to apply.
One key point is that the size of YourType
must be such that when you have an array:
YourType array[20];
then &array[1] == &array[0] + 1
. The byte address of &array[1]
must be incremented by sizeof(YourType)
, and (assuming YourType
is a structure), each of the elements of array[1]
must be properly aligned, just as the elements of array[0]
must be properly aligned.
Also remember types are defined in your compiled code to match the hardware you are working on. It is entirely up to the source code that is used to work this out.
So a low end chipset 16 bit targeted C program might have need to define types differently to a 32 bit system.
The programming language and compiler are what govern your types. Not the OS or hardware.
Although of course trying to stick a 32 bit number into a 16 bit register could be a problem!
C pointers are typed, unlike some old languages like PL/1. This not only allows the size of the object to be known, but so widening operations and formatting can be carried out. For example getting the data at *p, is that a float, a double, or a char? The compiler needs to know (think divisions, for example).
Of course we do have a typeless pointer, a void *
, which you cannot do any arithmetic with simply because the compiler has no idea how much to add to the address.
精彩评论