Can an address be assigned to a variable in C? - c

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

Related

Playing with pointer in c language

Could we point and address specific place in memory using pointer in c language?
Then modify it from another file (ANOTHER PROGRAM) and view it from any where.
Like :
Modifying it :
#include<stdio.h>
void main(){
int *p;
p= 12345678;
scanf("%d",p);
}
Viewing it :
#include<stdio.h>
void main(){
int *p;
p= 12345678;
printf("%d", *p);
}
No. Each process in your operating system has its own address space.
Processes can communicate, using the channels provided by the operating system.
Look into IPC, aka inter process communication, if you're interested in knowing more about it.
What about const volatile pointer (which will be pointing to some memory)? If I'm not wrong it will point to some memory it won't change during first program (also you will not be allowed to modify this memory) but that memory can be modified by another program/process etc.
EDIT:
Just to clarify if we use const volatile pointer it will do two things.
In program it won't allow us to change it value after initialisation
More important volatile keyword will disallow some compiler optimisations on readings and will always reload from memory each time it is accessed by the program. This dramatically reduces the possible optimisations. However, when the state of an object can change unexpectedly, it is the only way to ensure predictable program performance.

const int *ptr=500;where exactly it stored

I know that,in const int *ptr we can change the address but cannot change the value. i.e., ptr will be stored in read-write section(stack) and the object or entity will be stored in read-only section of data segement. So, we can change the address pointing by that pointer ptr, but cannot change the object which is constant.
int main()
{
const int *ptr=500;
(*ptr)++;
printf("%d\n",*ptr);
}
output is is assign the read only location to *ptr
int main()
{
const int *ptr=500;
ptr++;
printf("%d\n",*ptr);
}
No compilation errors, but at runtime the output is "segmentation fault".
I agree with the first one., why I am getting an segmentation fault in 2nd one? Where exactly they will be stored?
The reason for the segmentation fault is different from what you think.
It is not because of const.
It is because you are not allowed to access the area that you are trying to access when doing *ptr
When you make a pointer to "something", you are still not allowed to access the data (aka dereference the pointer) until you have made the pointer point to some memory that belongs to you.
Example:
int x = 0;
int* p = (int*)500;
int a = *p; // Invalid - p is not pointing to any memory that belongs to the program
p = &x;
int b = *p; // Fine - p is pointing to the variable x
p++;
int c = *p; // Invalid - p is not pointing to any memory that belongs to the program
The "invalid" code may give a segmentation fault. On the other hand, it may also just execute and produce unexpected results (or even worse: produce the expected result).
Lots of confusion here.
and the object or entity will be stored in read-only section of data segement
No, there is no requirement for where the pointed-at object is stored. This is only determined by any qualifiers/specifiers such as const or static, when declaring the pointed-at object.
const int *ptr=500;
This is not valid C and the code must result in a compiler message. An integer cannot get assigned to a pointer, there must be a conversion in between. GCC has a known flaw here, you have to configure it to be a standard compiler. gcc -std=c11 -pedantic-errors.
If you had code such as const int *ptr=(int*)500; which is valid C, then it would set the pointer to point at address 500. If there is an int at address 500, the code will work fine. If there is no memory there that you are allowed to access, then you will get some implementation-defined behavior like a crash - memory mapping is beyond the scope of the language.
(*ptr)++;
This is not valid C and the code must result in a compiler message. You are not allowed to modify a read-only location.
Overall, your compiler seems very poorly configured. GCC, correctly configured, gives 2 compiler errors.
const int *ptr=500; // WRONG
This declare a local variable which is a pointer to some constant integer. The const just tells the compiler that it is not allowed to update (overwrite) the dereferenced pointer memory cell.
However, your code is not correct; you probably want:
const int *ptr = (const int*)500;
The pointer is initialized to address 500 (you initialize the pointer).
On most systems, that address (and the following ones, e.g. at address 504 since sizeof(int) is 4) is out of the virtual address space. So dereferencing it (with *ptr) is undefined behavior and would often give some segmentation fault. See also this.
ptr will be stored in read-write section(stack) and the object or entity will be stored in read-only section of data segement.
This is wrong. Nothing is done at compilation time to keep the memory zone in a read-only text segment (however, most compilers are putting most literals or const static or global data -defined at compile-time- in it). Just you forbid the compiler to update the pointed thing (without cast).
If you need a read-only memory zone at runtime, you need to ask your OS for it (e.g. using mmap(2) & mprotect(2) on Linux). BTW protection works in pages.
On Linux, use pmap(1) (or proc(5), e.g. read sequentially the pseudo file /proc/self/maps from your program). You may want to add
char cmdbuf[64];
snprintf(cmdbuf, sizeof(cmdbuf), "pmap %d", (int) getpid());
system(cmdbuf);
before any dereference of ptr in your code to understand what is its virtual address space.
Try
cat /proc/self/maps
and
cat /proc/$$/maps
and understand their output (notice that $$ is expanded to the pid of your shell). Maybe experiment also strace(1) on your faulty program (which you should compile with gcc -Wall -g).

Doubts about pointer and memory access

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.

How to access something at a known memory address? [duplicate]

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.

Why do I get a segmentation fault if I print the contents of this memory location

Suppose I do the following
int *p = 1;
printf("%d", *p);
I get a segfault. Now, as I understand it, this memory location 1 is in the address space of my program. Why should there be a problem in reading this memory location ?
Your pointer doesn't point to anything valid. All you do is assign the value 1 to a pointer-to-int, but 1 isn't a valid memory location.
The only valid way to obtain an pointer value is either take the address-of a variable or call an allocation function:
int a;
int * p1 = &a; // OK
int * p2 = malloc(sizeof(int)); // also OK
*p1 = 2;
*p2 = 3;
As for "why there should be a problem": As far as the language is concerned, if you dereference an invalid pointer, you have undefined behaviour, so anything can happen -- this is really the only sensible way to specify the language if you don't want to introduce any arbitrary restrictions, and C is all about being easy-to-implement.
Practically, modern operating systems will usually have a clever virtual memory manager that needs to request memory when and as needed, and if the memory at address 1 isn't on a committed page yet, you'll actually get an error from the OS. If you try a pointer value near some actual address, you might not get an error (until you overstep the page boundary, perhaps).
To answer this properly will really depend upon a number of factors. However, it is quite likely that the address 0x00000001 (page 0) is not mapped and/or read protected.
Typically, addresses in the page 0 range are disallowed from a user application for one reason or another. Even in kernel space (depending upon the processor), addresses in page 0 are often protected and require that the page be both mapped and access enabled.
EDIT:
Another possible reason is that it could be segfaulting is that integer access is not aligned.
Your operating system won't let you access memory locations that don't belong to your program. It would work on kernel mode though...
No, address 1 is not in the address space of your program. You are trying to access a segment you do not own and receive segmentation fault.
You're trying to print 1, not the memory location. 1 isn't a valid memory location. To print the actual memory location do:
printf("%p", p);
Note the %p as icktoofay pointed out.

Resources