You have an operating system, which has 2 functions dealing with memory allocation:
void *malloc( int sz ) // allocates a memory block sz bytes long
void free( void *addr ) // frees a memory block starting at addr
// (previously allocated by malloc)
Using these functions, implement the following 2 functions:
void *malloc_aligned( int sz ) // allocates a memory block sz bytes long,
// aligned to an address divisible by 16
void free_aligned( void *addr ) // frees a memory block starting at addr
// (previously allocated by malloc_aligned)
in the solution there is the following part:
void * aligned_malloc(size_t size){
unsigned char *res=malloc(size+16);
unsigned char offest=16-((long)res%16);
What I don't understand is: Why do we need to use unsigned char and why and what we achieve using 16-((long)res%16); and what is the purpose of (long)res in this case?
You can't do pointer arithmetic on "void *", because void has no size.
When adding to a pointer or subtracting to it, it's always done in units of sizeof(*p). Meaning - if you add one to an int pointer, its value grows by 4 (because the size of an integer is 4). So when you add to a void pointer, it should grow by the size of a void. But void has no size.
However, some compilers are willing to do arithmetic on void *, and they treat it like char *. With these compilers, you could implement these functions without casting. But it isn't standard.
Another point is that not all operators are applicable for pointers. Addition and subtraction are, but multiplication, division and modulus are not. So if you want to test the low bits of a pointer, to know if it's aligned, you cast it to a long.
Why long? The assumption is that long is as large as a pointer, which is true in Linux, but not in Windows. The right type is uintptr_t. However, if you're only interested in the low bits, it doesn't matter if you lose the high bits while casting. So a cast to int would have worked too.
Related
I have a pointer char *a pointing to a block of memory. I have another pointer char *b that points to a memory block. Let's say b points to address 0x10001111. I want to write this address to next 8 bytes to the memory block pointed by a. In short, when I deference a, I should get the next 8 bytes of memory and value = 0x10001111. How do I do that? This is a x86_64 machine.
My current code:
static void write_add(void *a, char *b)
{ *(unsigned long *)a= (unsigned long)b;
*(unsigned long *)a= (unsigned long)b;
return;
}
I see only 0x00001111 on dereferencing a. Why am I not able to see the complete address?
Why would you involve a separate, unrelated type of uncertain size? If you want to store the pointer value in exactly 8 bytes (and supposing that the value fits in 8 bytes), you would spell that like so:
#include <stdint.h>
static void write_add(void *a, char *b) {
*(uint64_t *) a = (uint64_t) b;
}
You could also use memcpy(), but that seems a bit heavy-handed.
Do note, however, that C guarantees nothing about the size of the representation of pointer values. Although it is likely that 64 bits is enough on your system, you cannot safely assume that it is enough on every system.
unsigned long is not necessarily 64 bits on your platform. You can't make that assumption simply because you're on a x86_64 platform. I'm willing to bet it's actually 32 bits.
You should use uintptr_t instead as suggested by cad. This type is always defined to be a type that is big enough to contain a pointer on your platform.
For my C application I tried to initialize memory. I am aware of the slower calloc, but fortunatelly there is no need to track performance.
I need memory space for just one unsigned int element (up to 65535).
This is the part of my code that doesn't work:
//Declaration
unsigned int part1;
//Allocation
part1 = (unsigned int) calloc (1,sizeof(unsigned int));
That throws the compiler warning:
warning: cast from pointer to integer of different size
[-Wpointer-to-int-cast]
Why does the above code doesn't work, where...
unsigned long size;
size =(unsigned long) calloc (1,sizeof(unsigned long));
...works great?
Thank you!
calloc returns void* so you should use it like
unsigned int* part1 = calloc (1,sizeof(*part1));
then assign it like
*part1 = 42;
If you have allocated space for several elements
part1[0] = 42; // valid indices are [0..nmemb-1]
may be clearer.
Note that you also have to free this memory later
free(part1);
Alternatively, if you only need a single element, just declare it on the stack
unsigned int part1 = 42;
Regarding why casting a point to unsigned long doesn't generate a warning, sizeof(void*)==sizeof(unsigned long) on your platform. Your code would not be portable if you relied on this. More importantly, if you use a pointer to store a single integer, you'd leak your newly allocated memory and be unable to ever store more than one element of an array.
Use code below. Calloc() will return void* So you will have to convert it in the SomeType*
unsigned int* part1;
//Allocation
part1 = (unsigned int*) calloc (1,sizeof(unsigned int));
you have to understand these types of memory allocation to avoid doing these errors :
Static memory allocation:
unsigned int part1;
The size is fixed. It needs to be known at compile time. Freeing the memory is done on scope exit directly. The variable is allocated on the stack.
indeed, this type of memory allocation is done at compile time, its lifetime is entire runtime of program.
the advantage of using this type of allocation is efficient execution time.
but if we declare more static data space than we need we waste space, this is the disadvantage of this type.
Dynamic memory allocation:
unsigned int* part1 = calloc( n, sizeof(unsigned int) );
The size can vary, you can find the value at runtime. You are responsible for freeing the memory with free() predefined C function. The variable is allocated on the heap.
you can see more details in web site : http://www.cs.virginia.edu/~son/cs414.f05/lec11.slides.pdf
I am writing some very low-level C code to emulate a "file system" for a homework project. The file system is made of fixed-size blocks (1024B) but a "file" is allowed to span multiple non-consecutive blocks.
I need to be able to write any kind of void *buf to a file with a function that mimics write. Let's say we have the following signature myWrite(int blockNum, void *buf, int nbytes.
Let's say nbytes is greater than 1024 so I have to write to multiple blocks. So I'd need to do something like:
int remainder = nbytes - 1024;
myWrite(firstBlock, buf, 1024);
myWrite(nextBlock, (buf + 1024), remainder);
myWrite calls the standard write function underneath, passing in similar arguments.
The problem is with the pointer arithmetic, C doesn't like when I do pointer arithmetic on a void*. I get a EINVAL or EARGS (depending on Mac vs. Linux) saying that C doesn't like the pointer I passed to the write system call since it was produced via void pointer arithmetic.
The problem is, I don't know what kind of data type I will be writing. Sometimes it's a char * and other times it's something custom like a my_type * that represents a struct from the program code.
Is there any way around this? I need to have a generalized write like this. My current implementation works most of the time, but sometimes it fails.
Stick to using void *-pointers.
When the need for byte wise pointer arithmetic arises just cast the void *-pointer to char * (as sizeof(char) is defined to be equal to 1):
int a[2] = {47, 11};
void * p = &a[0];
printf("%d\n", *((int *)p)); /* Prints 47. */
p = ((char *) p) + sizeof(a[0]); /* Increments p by sizeof(int) bytes. */
printf("%d\n", *((int *)p)); /* Prints 11. */
Also as a note,: To type integers describing amounts of memory or indexes use size_t as it is guaranteed to be wide enough to address/index everything on the machine the code is compiled for.
The problem is with the pointer arithmetic, C doesn't like when I do pointer arithmetic on a void*
That's correct: C prohibits you from adding integers to void*, because it does not know how to convert the number to a number of bytes by which to advance the pointer. Normally, the multiplier can be derived from the type of the pointer. void*, however, does not have a type, hence C prohibits the arithmetic on it.
C does not mind if you do pointer arithmetic on other pointer types where the size is known. You can convert your void* pointer to a uint8_t* pointer, a char* pointer, or any other pointer to a type where sizeof(*ptr) is equal to 1, and do the arithmetic on it right before doing the arithmetic operations:
myWrite(nextBlock, ((char*)buf) + 1024, remainder);
The functions themselves should continue taking void*.
I have a function that will be passed a void pointer. This pointer can either be an int, char, or float. I know what data type will be passed to me by means of an associated value. For example, below is what my function looks like:
void * (int type, void * data);
If the void pointer I am passed was originally a char type, and I cast it back to a char type, is there a way of determining how many bytes are associated with that pointer? For example, if my function is called as follows:
f(1, (void *)"Hello world");
and I cast the void pointer back to a char pointer
char * p = (char *)data;
Is there some way I can figure out how many bytes were used? Would I possibly have to search for the null character and count how many bytes away it is from the original pointer? What would I have to do to find the size of the int and float as well?
Would I possibly have to search for the null character and count how
many bytes away it is from the original pointer?
Yes, if your void* is actually a char* this will work.
What would I have to do to find the size of the int and float as well?
int and float as always the same size (it depends from your architecture, generally 32 or 64 bit. Use sizeof operator to determine the exact size). If you are passing an array of int as void* you haven't any way to find its length.
Generally in these cases it's convinent to pass the size to your function too.
I'm a bit confused with a void* pointer in C. Especially after reading this question: Is the sizeof(some pointer) always equal to four?, where one person says there is no guarantee that sizeof(int *) == sizeof(double *)
My question is: is there a guarantee of sizeof(void*) >= sizeof(any other pointer type)?
In other words, can I always assign a some_type* pointer to a void* pointer and then get it back as some_type*?
Only data pointers. void * can hold any data pointer, but not function pointers.
Here is a C FAQ.
void *'s are only guaranteed to hold object (i.e. data) pointers; it
is not portable to convert a function pointer to type void *. (On some
machines, function addresses can be very large, bigger than any data
pointers.)
As for the first part, yes, different types can have pointers of different sizes:
The value stored in the pointer is an address to memory. If you're on a 32-bit system, that pointer into memory is going to be 32 bits (or four bytes) long. If you're on a 64-bit system, that pointer into memory is going to be 64 bits (or eight bytes) long.
The size of the data that holds the location in memory has nothing to do with the size of the data represented at that location in memory.
As for how a char * differs from a double *, the char * can point to any location, but the double * has to point to something along an eight-byte boundary. Larger data has to be aligned according to the rules of the processor you're on. So, pointers to small data are not generally compatible with pointers to large data (e.g. you shouldn't point a double * pointer to a char * address); but you're save going in the other direction (e.g. you can point a char * pointer to a double * address).