This question already has answers here:
memory address literal
(2 answers)
Closed 6 years ago.
I know it is possible to find the memory address of a variable or function with the & operator. But if I know that something is at memory position 2, how can I access it?
For instance, if I declare a pointer to 2, it will be read as the value 2, not the memory address 2.
You just need to cast it to be a pointer:
int *pointerToTwo = (int *)2;
Then you can dereference as usual:
int valueAtTwo = *pointerAtTwo;
The usual reason you'd do this kind of thing is to access memory mapped registers, in which case using the volatile keyword is advised:
int valueAtTwo = *(volatile int *)2;
Or maybe stick all the casting into a macro to make your code easier to read:
#define intValueAt(x) (*(volatile int)(x))
int valueAtTwo = intValueAt(2);
Aside: 2 is almost certainly not a valid address for this use case. I just used it because of your reference in your question.
void* pMemory = (void*)2L;
This will create a void* (void pointer) and set its address to 2.
Note that if your process shouldn't be accessing that memory (you don't have permissions to read from it), this can cause all sorts of errors. Also note that you shouldn't be reading addresses at random. Using pointers to directly access memory locations is prone to errors. This is why software developers have developed so much technology to help us with only accessing the correct memory addresses under the correct circumstances using the correct expected data types.
You can just cast it to int* to get a pointer, like this:
int *ptr = (int *)2;
Then you can access the content of 2 by normal * operator.
int i = *ptr;
will do what you want.
However, it is worth noting that in practice, the 'i' above is not the actual content of the second cell of your RAM. This is because in user-mode applications, the '2' is always treated as a virtual address and is translated (at runtime) to a physical address. Usually there is no way to do such things in user-mode codes in Unix-like OS.
Related
This question already has an answer here:
Pointer to a specific fixed address
(1 answer)
Closed 3 years ago.
I am sorry I know that's super basic question but I have to ask.
I have an array in integer type and I want to Assign it to specific memory address. How can I do that with C language?
For Example ;
int inputs[10] ={4,10,89};
So I want to Assign this inputs to 0x20000001.
Thank you so much.
Unless you are managing your memory allocation regions, say with linker scripts or other means, you should not do it. Compiler takes care of all memory allocation for you and does not provide any means for pre-defined memory addresses.
However, if you know what you are doing, you can use a pointer to handle it:
int *array = (int*)0x2000000;
now you can initialize it element by element, or by memcpy.
memcpy(array, inputs, sizeof(inputs));
You are likely to get segfault due to memory access violation if you are accessing restricted area of the memory, but here's a quick code to test it out if you know what address you are writing to:
int address = 0x20000001;
int *ptr;
ptr = (int*) address;
*ptr = inputs;
I'm learning about pointers and have been told this: "The purpose of pointers is to allow you to manually, directly access a block of memory."
Say I have int var = 5;. Can't I use the variable 'var' to access the block of memory where the value 5 is stored, since I can change the value of the variable whenever I want var = 6;? Do I really need a pointer when I can access any variable's value just by using its variable, instead of using a pointer that points to the address where the value is stored?
"The purpose of pointers is to allow you to manually, directly access a block of memory."
This is not always true. Consider
*(int*)(0x1234) = some_value;
this is "direct" memory access. Though
int a = some_value, *ptr = &a;
*ptr = some_other_value;
you are now accessing a indirectly.
Can't I use the variable 'var' to access the block of memory where the
value 5 is stored, since I can change the value of the variable
whenever I want var = 6; ?
Surely; but the semantics is different.
Do I really need a pointer when I can access any variable's value just by using its variable, instead of using a pointer that points to the address where the value is stored?
No, you don't. Consider the first example: within the scope where a has been declared, modifying its value through ptr is rather pointless! However, what if you are not within the scope of a? That is
void foo(int x)
{
x = 5;
}
int main(void)
{
int x = 10;
foo(x);
}
In foo, when you do x = 5, there is an ambiguity: do you want to modify foo::x or main::x? In the latter case that has to be "requested" explicitly and the fact that happens through pointers -or, better, through indirection- is a coincidence and a language choice. Other languages have others.
Pointer types have some traits that make them really useful:
It's guaranteed that a pointer will be so large that it can hold any address that is supported by the architecture (on x86, that is 32 bits a.k.a. 4 bytes, and an x64 64 bits a.k.a. 8 bytes).
Dereferencing and indexing the memory is done per object, not per byte.
int buffer[10];
char*x = buffer;
int*y = (int*)buffer;
That way, x[1] isn't y[1]
Both is not guaranteed if you use simple ints to hold your values. The first trait is at least guaranteed by uintptr_t (not by size_t though, although most of the time they have the same size - except that size_t can be 2 bytes in size on systems with segmented memory layout, while uintptr_t is still 4 bytes in size).
While using ints might work at first, you always:
have to turn the value into a pointer
have to dereference the pointer
and have to make sure that you don't go beyond certain values for your "pointer". For a 16 bit int, you cannot go beyond 0xFFFF, for 32 bit it's 0xFFFF FFFF - once you do, your pointer might overflow without you noticing it until it's too late.
That is also the reason why linked lists and pointers to incomplete types work - the compiler already knows the size of the pointers you are going to you, and just allocates memory for them. All pointers have the same size (4 or 8 bytes on 32-bit/64-bit architectures) - the type that you assign them just tells the compiler how to dereference the value. char*s take up the same space as void*s, but you cannot dereference void*s. The compiler won't let you.
Also, if you are just dealing with simple integers, there's a good chance that you will slow down your program significantly do to something called "aliasing", which basically forces the compiler to read the value of a given address all the time. Memory accesses are slow though, so you want to optimized these memory accesses out.
You can compare a memory address to a street address:
If you order something, you tell the shop your address, so that they can send you what you bought.
If you don't want to use your address, you have to send them your house, such that they can place the parcel inside.
Later they return your house to you. This is a bit more cumbersome than using the address!
If you're not at home, the parcel can be delivered to your neighbor if they have your address, but this is not possible if
you sent them your house instead.
The same is true for pointers: They are small and can be transported easily, while the object they point to
might be large, and less easily transportable.
With pointer arithmetics, pointers can also be used to access other objects than the one they originally pointed to.
You call a function from main() or from another function, the function you called can only return 1 value.
Let say you want 3 values changed, you pass them to the called function as pointers. That way you don't have to use global values.
One possible advantage is that it can make it easier to have one function modify a variable that will be used by many other functions. Without pointers, your best option is for the modifying function to return a value to the caller and then to pass this value to the other functions. That can lead to a lot of passing around. Instead, you can give the modifying function a pointer where it stores its output, and all the other functions directly access that memory address. Kind of like global variables.
i am just started learning pointers in c. I have following few doubts. If i find the answers for the below questions. It Will be really useful for me to understand the concept of pointers in c. Thanks in advance.
i)
char *cptr;
int value = 2345;
cptr = (char *)value;
whats the use of (char *) and what it mean in the above code snippet.
ii)
char *cptr;
int value = 2345;
cptr = value;
This also compiles without any error .then whats the difference between i & ii code snippet
iii) &value is returning address of the variable. Is it a virtual memory address in RAM? Suppose another c program running in parallel, will that program can have same memory address as &value. Will each process can have duplicate memory address same as in other process and it is independent of each other?
iv)
#define MY_REGISTER (*(volatile unsigned char*)0x1234)
void main()
{
MY_REGISTER=12;
printf("value in the address tamil is %d",(MY_REGISTER));
}
The above snippet compiled successfully. But it outputs segmentation fault error. I don't know what's the mistake I am doing. I want to know how to access the value of random address, using pointers. Is there any way? Will program have the address 0x1234 for real?
v) printf("value at the address %d",*(236632));//consider the address 236632 available in
//stack
why does the above printf statement showing error?
That's a type cast, it tells the compiler to treat one type as some other (possibly unrelated) type. As for the result, see point 2 below.
That makes cptr point to the address 2345.
Modern operating systems isolate the processes. The address of one variable in one process is not valid in another process, even if started with the same program. In fact, the second process may have a completely different memory map due to Address Space Layout Randomisation (ASLR).
It's because you try to write to address 0x1234 which might be a valid address on some systems, but not on most, and almost never on a PC running e.g. Windows or Linux.
i)
(char *) means, that you cast the data stored in value to a pointer ptr, which points to a char. Which means, that ptr points to the memory location 2345. In your code snipet ptr is undefined though. I guess there is more in that program.
ii)
The difference is, that you now write to cptr, which is (as you defined) a pointer pointing to a char. There is not much of a difference as in i) except, that you write to a different variable, and that you use a implicit cast, which gets resolved by the compiler. Again, cptr points now to the location 2345 and expects there to be a char
iii)
Yes you can say it is a virtual address. Also segmentation plays some parts in this game, but at your stage you don't need to worry about it at all. The OS will resolve that for you and makes sure, that you only overwrite variables in the memory space dedicated to your program. So if you run a program twice at the same time, and you print a pointer, it is most likely the same value, but they won't point at the same value in memory.
iv)
Didn't see the write instruction at first. You can't just write anywhere into memory, as you could overwrite another program's value.
v)
Similar issue as above. You cannot just dereference any number you want to, you first need to cast it to a pointer, otherwise neither the compiler, your OS nor your CPU will have a clue, to what exactely it is pointing to
Hope I could help you, but I recommend, that you dive again in some books about pointers in C.
i.) Type cast, you cast the integer to a char
ii.) You point to the address of 2345.
iii.) Refer to answer from Joachim Pileborg. ^ ASLR
iv.) You can't directly write into an address without knowing if there's already something in / if it even exists.
v.) Because you're actually using a pointer to print a normal integer out, which should throw the error C2100: illegal indirection.
You may think pointers like numbers on mailboxes. When you set a value to a pointer, e.g cptr = 2345 is like you move in front of mailbox 2345. That's ok, no actual interaction with the memory, hence no crash. When you state something like *cptr, this refers to the actual "content of the mailbox". Setting a value for *cptr is like trying to put something in the mailbox in front of you (memory location). If you don't know who it belongs to (how the application uses that memory), it's probably a bad idea. You could use "malloc" to initialize a pointer / allocate memory, and "free" to cleanup after you finish the job.
Is it possible to assign a variable the address you want, in the memory?
I tried to do so but I am getting an error as "Lvalue required as left operand of assignment".
int main() {
int i = 10;
&i = 7200;
printf("i=%d address=%u", i, &i);
}
What is wrong with my approach?
Is there any way in C in which we can assign an address we want, to a variable?
Not directly.
You can do this though : int* i = 7200;
.. and then use i (ie. *i = 10) but you will most likely get a crash. This is only meaningful when doing low level development - device drivers, etc... with known memory addreses.
Assuming you are on an x86-type processer on a modern operating system, it is not possible to write to aribtray memory locations; the CPU works in concert with the OS to protect memory so that one process cannot accidentally (or intentionally) overwrite another processes' memory. Allowing this would be a security risk (see: buffer overflow). If you try to anyway, you get the 'Segmentation fault' error as the OS/CPU prevents you from doing this.
For technical details on this, you want to start with 1, 2, and 3.
Instead, you ask the OS to give you a memory location you can write to, using malloc. In this case, the OS kernel (which is generally the only process that is allowed to write to arbitrary memory locations) finds a free area of memory and allocates it to your process. The allocation process also marks that area of memory as belonging to your process, so that you can read it and write it.
However, a different OS/processor architecture/configuration could allow you to write to an arbitrary location. In that case, this code would work:
#include <stdio.h>
void main() {
int *ptr;
ptr = (int*)7000;
*ptr = 10;
printf("Value: %i", *ptr);
}
C language provides you with no means for "attaching" a name to a specific memory address. I.e. you cannot tell the language that a specific variable name is supposed to refer to a lvalue located at a specific address. So, the answer to your question, as stated, is "no". End of story.
Moreover, formally speaking, there's no alternative portable way to work with specific numerical addresses in C. The language itself defines no features that would help you do that.
However, a specific implementation might provide you with means to access specific addresses. In a typical implementation, converting an integral value Ato a pointer type creates a pointer that points to address A. By dereferencing such pointer you can access that memory location.
Not portably. But some compilers (usually for the embedded world) have extensions to do it.
For example on IAR compiler (here for MSP430), you can do this:
static const char version[] # 0x1000 = "v1.0";
This will put object version at memory address 0x1000.
You can do in the windows system with mingw64 setup in visual studio code tool, here is my code
#include<stdio.h>
int main()
{
int *c;
c = (int *)0x000000000061fe14; // Allocating the address 8-bit with respect to your CPU arch.
*c = NULL; // Initializing the null pointer for allocated address
*c = 0x10; // Assign a hex value (you can assign integer also without '0x')
printf("%p\n",c); // Prints the address of the c pointer variable
printf("%x\n",*c); // Prints the assigned value 0x10 -hex
}
It is tested with mentioned environment. Hope this helps Happy coding !!!
No.
Even if you could, 7200 is not a pointer (memory address), it's an int, so that wouldn't work anyway.
There's probably no way to determine which address a variable will have. But as a last hope for you, there is something called "pointer", so you can modify a value on address 7200 (although this address will probably be inaccessible):
int *i = (int *)7200;
*i = 10;
Use ldscript/linker command file. This will however, assign at link time, not run time.
Linker command file syntax depends largely on specific compiler. So you will need to google for linker command file, for your compiler.
Approximate pseudo syntax would be somewhat like this:
In linker command file:
.section start=0x1000 lenth=0x100 myVariables
In C file:
#pragma section myVariables
int myVar=10;
It's not possible, maybe possible with compiler extensions. You could however access memory at an address you want (if the address is accessible to your process):
int addr = 7200;
*((int*)addr) = newVal;
I think '&' in &a evaluates the address of i at the compile time which i think is a virtual address .So it is not a Lvalue according to your compiler. Use pointer instead
This is actually a much more concise, much more clear question than the one I had asked here before(for any who cares): C Language: Why does malloc() return a pointer, and not the value? (Sorry for those who initially think I'm spamming... I hope it's not construed as the same question since I think the way I phrased it there made it unintentionally misleading)
-> Basically what I'm trying to ask is: Why does a C programmer need a pointer to a dynamically-allocated variable/object? (whatever the difference is between variable/object...)
If a C programmer has the option of creating just 'int x' or just 'int *x' (both statically allocated), then why can't he also have the option to JUST initialize his dynamically-allocated variable/object as a variable (and NOT returning a pointer through malloc())?
*If there are some obscure ways to do what I explained above, then, well, why does malloc() seem the way that most textbooks go about dynamic-allocation?
Note: in the following, byte refers to sizeof(char)
Well, for one, malloc returns a void *. It simply can't return a value: that wouldn't be feasible with C's lack of generics. In C, the compiler must know the size of every object at compile time; since the size of the memory being allocated will not be known until run time, then a type that could represent any value must be returned. Since void * can represent any pointer, it is the best choice.
malloc also cannot initialize the block: it has no knowledge of what's being allocated. This is in contrast with C++'s operator new, which does both the allocation and the initialization, as well as being type safe (it still returns a pointer instead of a reference, probably for historical reasons).
Also, malloc allocates a block of memory of a specific size, then returns a pointer to that memory (that's what malloc stands for: memory allocation). You're getting a pointer because that's what you get: an unitialized block of raw memory. When you do, say, malloc(sizeof(int)), you're not creating a int, you're allocating sizeof(int) bytes and getting the address of those bytes. You can then decide to use that block as an int, but you could also technically use that as an array of sizeof(int) chars.
The various alternatives (calloc, realloc) work roughly the same way (calloc is easier to use when dealing with arrays, and zero-fills the data, while realloc is useful when you need to resize a block of memory).
Suppose you create an integer array in a function and want to return it. Said array is a local variable to the function. You can't return a pointer to a local variable.
However, if you use malloc, you create an object on the heap whose scope exceeds the function body. You can return a pointer to that. You just have to destroy it later or you will have a memory leak.
It's because objects allocated with malloc() don't have names, so the only way to reference that object in code is to use a pointer to it.
When you say int x;, that creates an object with the name x, and it is referenceable through that name. When I want to set x to 10, I can just use x = 10;.
I can also set a pointer variable to point to that object with int *p = &x;, and then I can alternatively set the value of x using *p = 10;. Note that this time we can talk about x without specifically naming it (beyond the point where we acquire the reference to it).
When I say malloc(sizeof(int)), that creates an object that has no name. I cannot directly set the value of that object by name, since it just doesn't have one. However, I can set it by using a pointer variable that points at it, since that method doesn't require naming the object: int *p = malloc(sizeof(int)); followed by *p = 10;.
You might now ask: "So, why can't I tell malloc to give the object a name?" - something like malloc(sizeof(int), "x"). The answer to this is twofold:
Firstly, C just doesn't allow variable names to be introduced at runtime. It's just a basic restriction of the language;
Secondly, given the first restriction the name would have to be fixed at compile-time: if this is the case, C already has syntax that does what you want: int x;.
You are thinking about things wrong. It is not that int x is statically allocated and malloc(sizeof(int)) is dynamic. Both are allocated dynamically. That is, they are both allocated at execution time. There is no space reserved for them at the time you compile. The size may be static in one case and dynamic in the other, but the allocation is always dynamic.
Rather, it is that int x allocates the memory on the stack and malloc(sizeof(int)) allocates the memory on the heap. Memory on the heap requires that you have a pointer in order to access it. Memory on the stack can be referenced directly or with a pointer. Usually you do it directly, but sometimes you want to iterate over it with pointer arithmetic or pass it to a function that needs a pointer to it.
Everything works using pointers. "int x" is just a convenience - someone, somewhere got tired of juggling memory addresses and that's how programming languages with human-readable variable names were born.
Dynamic allocation is... dynamic. You don't have to know how much space you are going to need when the program runs - before the program runs. You choose when to do it and when to undo it. It may fail. It's hard to handle all this using the simple syntax of static allocation.
C was designed with simplicity in mind and compiler simplicity is a part of this. That's why you're exposed to the quirks of the underlying implementations. All systems have storage for statically-sized, local, temporary variables (registers, stack); this is what static allocation uses. Most systems have storage for dynamic, custom-lifetime objects and system calls to manage them; this is what dynamic allocation uses and exposes.
There is a way to do what you're asking and it's called C++. There, "MyInt x = 42;" is a function call or two.
I think your question comes down to this:
If a C programmer has the option of creating just int x or just int *x (both statically allocated)
The first statement allocates memory for an integer. Depending upon the placement of the statement, it might allocate the memory on the stack of a currently executing function or it might allocate memory in the .data or .bss sections of the program (if it is a global variable or static variable, at either file scope or function scope).
The second statement allocates memory for a pointer to an integer -- it hasn't actually allocated memory for the integer itself. If you tried to assign a value using the pointer *x=1, you would either receive a very quick SIGSEGV segmentation violation or corrupt some random piece of memory. C doesn't pre-zero memory allocated on the stack:
$ cat stack.c
#include <stdio.h>
int main(int argc, char *argv[]) {
int i;
int j;
int k;
int *l;
int *m;
int *n;
printf("i: %d\n", i);
printf("j: %d\n", j);
printf("k: %d\n", k);
printf("l: %p\n", l);
printf("m: %p\n", m);
printf("n: %p\n", n);
return 0;
}
$ make stack
cc stack.c -o stack
$ ./stack
i: 0
j: 0
k: 32767
l: 0x400410
m: (nil)
n: 0x4005a0
l and n point to something in memory -- but those values are just garbage, and probably don't belong to the address space of the executable. If we store anything into those pointers, the program would probably die. It might corrupt unrelated structures, though, if they are mapped into the program's address space.
m at least is a NULL pointer -- if you tried to write to it, the program would certainly die on modern hardware.
None of those three pointers actually point to an integer yet. The memory for those integers doesn't exist. The memory for the pointers does exist -- and is initially filled with garbage values, in this case.
The Wikipedia article on L-values -- mostly too obtuse to fully recommend -- makes one point that represented a pretty significant hurdle for me when I was first learning C: In languages with assignable variables it becomes necessary to distinguish between the R-value (or contents) and the L-value (or location) of a variable.
For example, you can write:
int a;
a = 3;
This stores the integer value 3 into whatever memory was allocated to store the contents of variable a.
If you later write:
int b;
b = a;
This takes the value stored in the memory referenced by a and stores it into the memory location allocated for b.
The same operations with pointers might look like this:
int *ap;
ap=malloc(sizeof int);
*ap=3;
The first ap= assignment stores a memory location into the ap pointer. Now ap actually points at some memory. The second assignment, *ap=, stores a value into that memory location. It doesn't update the ap pointer at all; it reads the value stored in the variable named ap to find the memory location for the assignment.
When you later use the pointer, you can choose which of the two values associated with the pointer to use: either the actual contents of the pointer or the value pointed to by the pointer:
int *bp;
bp = ap; /* bp points to the same memory cell as ap */
int *bp;
bp = malloc(sizeof int);
*bp = *ap; /* bp points to new memory and we copy
the value pointed to by ap into the
memory pointed to by bp */
I found assembly far easier than C for years because I found the difference between foo = malloc(); and *foo = value; confusing. I hope I found what was confusing you and seriously hope I didn't make it worse.
Perhaps you misunderstand the difference between declaring 'int x' and 'int *x'. The first allocates storage for an int value; the second doesn't - it just allocates storage for the pointer.
If you were to "dynamically allocate" a variable, there would be no point in the dynamic allocation anyway (unless you then took its address, which would of course yield a pointer) - you may as well declare it statically. Think about how the code would look - why would you bother with:
int x = malloc(sizeof(int)); *x = 0;
When you can just do:
int x = 0;