dereference an integer pointer on 64 bit platform - c

if we dereference an integer pointer, say * (int * )
as we know that integer pointer dominate 8 byte in 64 platform. but integer still takes 4 byte in 64 platform.
what if i want to dereference an pointer where the beginning of its memory contains another pointer address. so actually i want to take the value of the first 8 bytes. will dereference * (int *) get 4 byte or 8byte? i think it should be 4 byte as integer is 4 byte. but how can i get 8 byte in 64 bit platform? without knowing whether the platform is 32 or 64 bit.

Lets make some things clear (these are all platform independent but in MOST cases), if on your system:
sizeof(int) is 4 bytes
sizeof(int*) is 4 on 32bit and 8 on 64bit
sizeof(int**) is 4 on 32bit and 8 on 64bit
When you dereference an int*, you are extracting an int. The original int* may be 8 bytes on a 64bit but you will get 4 bytes from either 32bit or 64bit systems.
When you dereference an int**, you are extracting an int*. The original int** may be 4 bytes on 32bit or 8 bytes on a 64bit, but you will get 4 bytes from a 32bit system and 8 bytes from a 64bit system because you are extracting int*.

I'm not sure if I understand your problem right, but actually I think that you really don't have a problem at all, because the compiler will handle word sizes automatically for you, generating the proper code for each platform. So let's assume that you call a function that returns a pointer to a pointer to an int:
int** ppiValue = SomeFunction ();
If you dereference this pointer, you get a pointer to an int, which will have the proper size on each platform:
int* piValue = *ppiValue;
This will be 8 bytes on a 64-bit processor, or 4 bytes on a 32-bit processor. The compiler is responsible for choosing the right size for the selected target platform. Now let's dereference this pointer:
int iValue = *piValue;
This will be a 4-byte value on both processors. Once again, the compiler is responsible for generating proper machine code instructions.
So don't bother - as long as you rely on strong typing and don't use dangerous typecasts, the compiler will take care of the low-level indirection details.

Related

C programming pointer, bytes and memory allocation have 8 question

I am trying to get the bytes and pointers and how they are stored can any one explain or answer some of my questions. Thank you
int num = 513; <-- allocating a 4 bit memory by initializing
//[01][02][00][00] <-- (numbers are sorted and shown as litle endian)
char * ptr = &num; //char is (one byte)
↓
//[01][02][00][00]
// pointer always start from the [0] (as in this array byte length)
// in the allocated address in the memory ptr[0] is in this case = [01]
// (printed as %x02 "printf("the byte %02x\n",ptr[0]);" - if it's only
//single number 1 a zero will be added on the length so it prints out as 01)
int * ptr = &num; //now creating a pointer with the type of int (four bytes)
↓ ↓ ↓ ↓
//[01][02][00][00]
how can i access the first byte of this int pointer? [question01]
is there a way to see the bites inside the of the first byte([01])? [question02]
where does the pointer save the address? does it have to allocate a memory space in the ram to save whe address such as 0x233828ff21 and if so this(0x233828ff21) address requires a lot of bytes? [question03]
where does this int pointer stores it's type length (4bytes)? [question05]
what happens if i declare a type with longer byte memory allocation such as long long * ptr = &num; [01][02][00][00][00][00][00][00]
since i am pointing a long long to a 4 byte int, can those 4 last already been allocated by another program and in use? can i read it? [question06]
binary are only 0 and 1 and whether one of those(0 or 1) is called a bite? [question07]
one byte is 8 bits right? why am i getting 16 bits 0000000000000001 when converting the number 1 in this website (https://www.rapidtables.com/convert/number/decimal-to-binary.html) shouldn't it be 8? [question08]
Note: char * ptr = &num; should really be unsigned char * ptr = (unsigned char *)&num; to avoid compiler warnings and to ensure that the bytes are treated as unsigned values.
how can i access the first byte of this int pointer? [question01]
If you really want to access the first byte of a pointer, you can use:
unsigned char *ptr2 = (unsigned char *)&ptr;
then ptr2[0] is the first byte of the pointer ptr.
is there a way to see the bites inside the of the first byte([01])? [question02]
I assume you mean the bits inside the first byte. Bits are not directly addressable, so you need an expression (usually with bit-wise operators) to get the value each bit. For example, (ptr[m] >> n) & 1 will be the value of the nth bit of the mth byte of an object (where ptr is an unsigned char * pointing to the start of the object).
where does the pointer save the address? does it have to allocate a memory space in the ram to save whe address such as 0x233828ff21 and if so this(0x233828ff21) address requires a lot of bytes? [question03]
Addresses are stored in pointer variables in the same way as numbers are stored in variables of numeric type. At the CPU instruction level, there is no difference between a stored pointer value and a stored integer value, other than the width.
The most typical sizes of pointer types are 8 bytes or 4 bytes, depending on the target architecture of the compiler.
(There is no question04.)
where does this int pointer stores it's type length (4bytes)? [question05]
It doesn't store the length of the type, but the compiler knows that a TYPE * points to an object that is sizeof(TYPE) bytes long.
what happens if i declare a type with longer byte memory allocation such as long long * ptr = # [01][02][00][00][00][00][00][00] since i am pointing a long long to a 4 byte int, can those 4 last already been allocated by another program and in use? can i read it? [question06]
If the pointer is not correctly aligned for the referenced type (long long) then the behavior is undefined. Otherwise it can be converted back to the original pointer type int *. In any case, accessing *ptr will result in undefined behavior (unless long long is the same width as int, which is not typical).
binary are only 0 and 1 and whether one of those(0 or 1) is called a bite? [question07]
It is called a bit. There is also a type called _Bool. Expressions of type _Bool always have the value 0 or 1.
one byte is 8 bits right? why am i getting 16 bits 0000000000000001 when converting the number 1 in this website (https://www.rapidtables.com/convert/number/decimal-to-binary.html) shouldn't it be 8? [question08]
Who cares what some random web-site displays?
What C calls a "byte" is any type where sizeof(type) is 1, including char, signed char and unsigned char. It is at least 8 bits wide, but is wider than 8 bits on some exotic systems.
A pointer of character type (char *, signed char * or unsigned char *) can be used to access the individual bytes within any object, but that might not be true for pointers of other size 1 types, and is certainly not true for pointer to _Bool (_Bool *)!
• how can i access the first byte of this int pointer? [question01]
Generally, it is preferable to use unsigned char rather than char to access arbitrary bytes, so let’s do that.
After unsigned char *ptr = &num;, ptr is a pointer to unsigned char, and you could access the first byte of the int with *ptr or ptr[0], as in printf("The first byte, in hexadecimal, is 0x%02hhx.\n", *ptr);.
If instead you have int *ptr = &num;, there is no direct way to access the first byte. ptr here is a pointer to an int, and, to access an individual byte, you need a pointer to an unsigned char or other single-byte type. You could convert ptr to a pointer to unsigned char, as with (unsigned char *) ptr, and then you can access the individual byte with * (unsigned char *) ptr.
• is there a way to see the bites inside the of the first byte([01])? [question02]
The C standard does not provide a way to display the individual bits of a byte. Commonly programmers print the values in hexadecimal, as above, and read the bits from the hexadecimal digits. You can also write your own routine to write binary output from a byte.
• where does the pointer save the address? does it have to allocate a memory space in the ram to save whe address such as 0x233828ff21 and if so this(0x233828ff21) address requires a lot of bytes? [question03]
A pointer is a variable like your other int and char variables. It has space of its own in memory where its value is stored. (This model of variables having memory is used to specify the behavior of C programs. When a program is optimized by a compiler, it may change this.)
In current systems, pointers are commonly 32 or 64 bits (four or eight 8-bit bytes), depending on the target architecture. You can find out which with printf("The size of a 'char *' is %zu bytes.\n", sizeof (char *));. (The C standard allows pointers of different types to be different sizes, but that is rare in modern C implementations.)
• where does this int pointer stores it's type length (4bytes)? [question05]
The compiler knows the sizes of pointers. The pointer itself does not store the length of the thing it is pointing to. The compiler simply generates appropriate code when you use the pointer. If you use *ptr to get the value that a pointer points to, the compiler will generate a load-byte instruction if the type of ptr is char *, and it will generate a load-four-byte instruction of the type of ptr is int * (and int is four bytes in your C implementation).
• what happens if i declare a type with longer byte memory allocation such as long long * ptr = # [01][02][00][00][00][00][00][00] since i am pointing a long long to a 4 byte int, can those 4 last already been allocated by another program and in use? can i read it? [question06]
When long long is an eight-byte integer, and you have a long long *ptr that is pointing to a four-byte integer, the C standard does not define the behavior when you attempt to use *ptr.
In general-purpose multi-user operating systems, the memory after the int cannot be allocated by another program (unless this program and the other program have both arranged to share memory). Each process is given its own virtual address space, and their memory is kept separate.
Using this long long *ptr in your program may access memory beyond that of the int. This can cause various types of bugs in your program, including corrupting data and alignment errors.
• binary are only 0 and 1 and whether one of those(0 or 1) is called a bite? [question07]
One binary digit is a “bit”. Multiple binary digits are “bits”.
The smallest group of bits that a particular computer operates on as a unit is a “byte”. The size of a byte can vary; early computers had bytes of different sizes. Modern computers almost all use eight-bit bytes.
If your program includes the header <limits.h>, it defines a macro named CHAR_BIT that provides the number of bits in a byte. It is eight in almost all modern C implementations.
• one byte is 8 bits right? why am i getting 16 bits 0000000000000001 when converting the number 1 in this website (https://www.rapidtables.com/convert/number/decimal-to-binary.html) shouldn't it be 8? [question08]
The web site is not merely converting to one byte.
It seems to show at least 16 bits, choosing the least of 16, 32, or 64 bits that the value fits in as a signed integer type.

how is the size of every pointer variable being 8 bytes on a 64-bit machine justified?

I went through pointer arithmetic and the fact that you can't assign pointer of one data type to another data type. for example, below declaration is incorrect.
double x = 10;
int *ptrInt = &x;
We've assigned the address of double variable to a "pointer to integer". Double takes 8 bytes as compared to an integer, that takes 4 bytes and therefore an integer pointer will truncate those extra 4 bytes.
But how come, the size of any pointer variable is 8 bytes and that also means it will not truncate those extra 4 bytes and should work correctly(even though it doesn't).
I have this doubt. Can anybody help me with the clarification?
how come, the size of any pointer variable is 8 bytes ? pointer variable contains address & size of address is 8 byte on 64-bit system irrespective of whether pointer variable points to int or char or float objects as 64-bit pointer supports 8 byte address space.

Getting a pointer to a memory address from a different pointer C

I'm writing my own memory allocater. I'm getting a pointer to mapped memory from mmap. From there, I want to be able to get a pointer to a different part of that mapped memory (like x bytes away from the current pointer). How can I do this? Memory management is very confusing to me.
mmap gives you a void* and C doesn't allow pointer arithmetic with those, but you can cast it to char* and then just add the number of bytes you want, e.g. mypointer + 16.
If you cast the pointer to a larger type (like int*), pointer arithmetic adds multiples of the size of that type. For example, if you add 16 to an int*, you're adding enough bytes for 16 int values (so 64 bytes, assuming sizeof(int) is 4).

Why is a pointer to a pointer to a function 8 byte?

I know a pointer to a function is 8 byte because of virtualization but why a pointer to a pointer to a function is 8 byte?
typedef void(*fun())();
sizeof(fun*); // returns 8 byte
If you have a 64-bit system with 8-bit bytes (and it sounds like you do), probably all pointers will be 8 bytes in size. Virtualization doesn't have anything to do with it.
It's because they're both pointers to memory addresses regardless of what kind of data they point to, and you're running on a 64-bit system
If memory addresses were say... 4 bytes, than it would be impossible to have more than 4GB of ram on your computer. there just wouldn't be enough different pointer values.
pointer to a pointer to a function is 8 byte?
it is also a pointer.
char *, int *, float * and etc all these pointers Have same size and also function pointer.
Size of pointer is dependent on architecture.
On most architectures Size of pointer is same In your case 8 bytes(64-bit)
on 32-bit size is 4 bytes,
Adding this based on # Grijesh Chauhan comment.
There have been architectures where pointers to different types have different sizes.
You have a 64-bit machine with a 64-bit address word, which happens to be 8 bytes. A pointer is just a memory address, which because of how many bits are in your address space is 8 bytes.
It would be 4 bytes if you were running a 32 bit OS, or 2 bytes on a 286+DOS.

Is size of char * same as size of int *?

I know:
char * is a pointer to char.
and
int * is a pointer to int.
So, i want to confirm following two things:
So now suppose I am on 32 bit machine, then that means memory addresses are 32 bit wide.
Thus that means size of char * and int * is both 32 bits ( 4 bytes), right ?
Also is size of char * * also same as size of int * ?
suppose I have:
int * ptr;
Thus now doing *((char * *) ptr) = 0x154 is same as *((int *) ptr) = 0x514 same, right ?
( 0x514 is just any random memory address)
Platform: I am on x86.
P.S.: I know type casting is not a suggested way to code. But I am doing Kernel coding, thus I HAVE TO do type casting !
In C pointers are not guaranteed to have the same size. Now in reality most implementations pointers will be the same size, but that is an implementation detail of the compiler.
From the C Faq:
The old HP 3000 series uses a different addressing scheme for byte
addresses than for word addresses; like several of the machines above
it therefore uses different representations for char * and void *
pointers than for other pointers
Depending on the ``memory model'' in use, 8086-family processors (PC
compatibles) may use 16-bit data pointers and 32-bit function
pointers, or vice versa.
Also *((char *)ptr) = 0x154 is not the same as *((int *)ptr) = 0x154. Because you are dereferencing the pointer you will write data the size of a char and the size of an int into the location pointed to by ptr. Assuming an 8 bit char and a 32 bit int, *((char *)ptr) = 0x154 will write0x154 to the memory address assigned to ptr and *((int *)ptr) = 0x154 will write 0x0000000154 to the 4 bytes starting at the address assigned to ptr.
Technically speaking, the C standard only guarantees that sizeof(char) == 1, and the rest is up to the implementation. But on modern x86 architectures (e.g. Intel/AMD chips) it's fairly predictable.
You've probably heard processors described as being 16-bit, 32-bit, 64-bit, etc. This usually means that the processor uses N-bits for integers. Since pointers store memory addresses, and memory addresses are integers, this effectively tells you how many bits are going to be used for pointers. sizeof is usually measured in bytes, so code compiled for 32-bit processors will report the size of pointers to be 4 (32 bits / 8 bits per byte), and code for 64-bit processors will report the size of pointers to be 8 (64 bits / 8 bits per byte). This is where the limitation of 4GB of RAM for 32-bit processors comes from -- if each memory address corresponds to a byte, to address more memory you need integers larger than 32-bits.
In practice, pointers will be size 2 on a 16-bit system (if you can find one), 4 on a 32-bit system, and 8 on a 64-bit system, but there's nothing to be gained in relying on a given size

Resources