Confused on how memory is allocated - c

I am watching a video on pointers and memory and I'm confused because I thought memory addresses are 1 byte but in the video he is saying they are 32-bits (4 bytes) and that if we had int a = 2 it would be stored in one memory address, but wouldn't an integer be stored across 4 separate memory addresses since they are a maximum 4 bytes long?

A pointer points to a single byte. When you're storing something larger than a byte, it's spread across multiple consecutive bytes, and the pointer points to the first of these bytes. The compiled code uses instructions that can read and write multiple bytes from memory to process the whole thing.
So you're correct, a 32-bit integer will be stored in 4 separate (but consecutive) memory locations.
This is why we have to declare the types of pointers in C. When you derefence the pointer, the type is used to determine how many bytes to read or write starting at that address.

Related

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).

Does malloc takes care of memory allignment?

I allocated 5 bytes of memory using malloc and I was able to use those 5 bytes to store characters or integers.
For example,use the first byte to store a character and the next four bytes to store an integer.
How does malloc takes care of memory allignment issues?
malloc
If allocation succeeds, returns a pointer to the lowest (first) byte
in the allocated memory block that is suitably aligned for any object
type.
So the memory block is aligned for any object type.
use the first byte to store a character and the next four bytes to
store an integer.
That's not valid. You need to either bundle the char and integer together in a structure (which might include padding) or have 2 separate memory blocks for them. Or serialize them (which is another issue).

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.

Memory allocated without allocation using malloc, how?

Below is a simple code snippet:
int main()
{
int *p;
p=(int*)malloc(sizeof(int));//allocate m/y 4 1 int
printf("P=%p\tQ=%p",p,p+2);
}
In one sample run, it gave me the output as below:
P=0x8210008 Q=0x8210010
Starting address of P is-P=0x8210008,next byte is 0x8210009,next byte is 0x821000A,next byte is 0x821000B.So the 4 bytes for int is ending there.
We haven't allocated more memory using malloc.
Then how is p+2 leading us to 0x8210010,which is 8 bytes after P(0x8210008).
Because it's treating it as an integer-element offset from the pointer. You have allocated an array for a single integer. When you ask for p+2 it's the same as &p[2]. If you want two bytes from the beginning, you need to cast it to char* first:
char *highWordAddr = (char*)p + 2;
First, the fact that you have printed an address does not imply that memory is allocated at that address. You have simply added numbers and produced other numbers.
Second, the reason that you number you got by adding two was eight greater than the base address instead of two greater than the base address was because, when you add integers to pointers in C, the arithmetic is done in terms of pointed-to elements, not in terms of bytes in memory (unless the pointed-to elements are bytes). Suppose you have an array of int, say int x[8], and you have a pointer to x[3]. Adding two to that pointer produces a pointer to x[5], not a pointer to two bytes beyond the start of x[3]. It is important to remember that C is an abstraction, and the C standard specifies what happens inside that abstraction. Inside the C abstraction, pointer arithmetic works on numbers of elements, not on raw memory addresses. The C implementation (the compiler and the tools that turn C code into program execution) is required to perform whatever operations on raw memory addresses are required to implement the abstraction specified by the C standard. Typically, that means the compiler multiplies an integer by the size of an element when adding it to a pointer. So two is multiplied by four (on a machine where an int is four bytes), and the eight that results is added to the base address.
Third, you cannot rely on this behavior. The C standard defines pointer arithmetic only for pointers that point to objects inside arrays, including one fictitious object at the end of the array. Additionally, pointers to individual objects act like arrays of one element. So, if you have a pointer p that points to an int, you are allowed to calculate p+0 or p+1, because they point to the only object in the array (p+0) and the fictitious object one beyond the last element in the array (p+1). You are not allowed to calculate p-1 or p+2, because these are outside the array. Note that this is not a matter of dereferencing the pointer (attempting to read or write memory at the calculated address): Even merely calculating the address results in behavior that is not defined by the C standard: Your program could crash, it could give you “correct” results, or it could delete all files in your account, and all of those behaviors would be conforming to the C standard.
It is unlikely that merely calculating an out-of-bounds address would produce such weird behavior. However, the standard permits it because some computer processors have unusual address schemes that require more work than simple arithmetic. Perhaps the second-most common address scheme after the flat address space is a base address and offset scheme. In such a scheme, the high 16 bits of a four-byte pointer might contain a base address, and the low 16 bits might contain an offset. For a given base address b and offset o, the corresponding virtual address might be 4096*b+o. (Such a scheme is capable of addressing only 220 bytes, and many different values of base and offset can refer to the same address. For example, base 0 and offset 4096 refer to the same address as base 1 and offset 0.) With a base-and-offset scheme, the compiler might implement pointer arithmetic by adding only to the offset and ignoring the base. (Such a C implementation can support arrays only up to 65536 bytes, the extent addressable by the offset alone.) In such an implementation, if you have pointer-to-int p with an encoding of 0x0000fffc (base 0, offset 65532), and int is four bytes, then p+2 will have the value 0x00000004, not the value that is eight greater (0x00010004).
That is an example where pointer arithmetic produces values that you would not expect from a flat-address machine. It is harder to imagine an implementation where pointer arithmetic that is not valid according to the C standard would produce a crash. However, consider an implementation in which memory must be manually swapped by a process, because the processor does not have the hardware to support virtual memory. In such an implementation, pointers might contain addresses of structures in memory that describe disk locations and other information used to manage the memory swapping. In such an implementation, doing pointer arithmetic might require reading the structures in memory, and so doing invalid pointer arithmetic might reading invalid addresses.
C is happy to let you do whatever pointer arithmetic you like. Just because p+2 looks like any other address doesn't mean it's valid. In fact, in this case, it's not.
Be very careful any time you see pointer arithmetic that you're not going outside your allocated bounds.
This is called pointer arithmetic. http://www.learncpp.com/cpp-tutorial/68-pointers-arrays-and-pointer-arithmetic/

Copying an array in C

What is wrong with this statement? It doesn't copy right.
memcpy(new_board1, board, sizeof(board));
memcpy accepts two memory addresses in form of pointers (destination and source) and the number of bytes to be copied. Now, sizeof doesn't return the size of the memory block a pointer points to, but the size of the pointer itself - either 4 bytes on a 32bit OS, or 8 bytes on a 64bit OS.
sizeof(board) gives you the size of the pointer itself, not the size of whatever it points at. You should replace it by the actual number of bytes you want to copy from board to new_board1. Without knowing how boardand new_board1 are declared, I cannot help you find that number.

Resources