Is it possible to find out the variable name, the pointer pointing to? - c

Is it Possible to get the name of array the pointer pointing to?
example:
char name[20];
char *p = name
int door_no;
int *q = &door_no
In the above example we are giving the base address of the array with the array name and pointer q pointing to door_no but what if, I have to know the name of the variable the array is pointing to? What is the variable name pointer q is pointing to? Is it possible? I tried and came to the conclusion that it's not possible but still I am trying to get the solution. What you think guys? Is there any way to make it possible?

No, you can't do that. The names of variables do not even exist after your code is compiled and linked (unless you're keeping debugging information around), so you can't get at it at run time.
In C (in contrast to very dynamic languages such as JavaScript or classical Lisp), the only role of variable names is to tell the compiler/linker which declaration you're pointing at when you mention a variable in the source code. Once these connections have been made and represented in the compiler's internal data structures, there is no further use for the names (again, except for debugging and/or pretty-printing of error messages from the compiler).

Everything that Henning said before me is correct. In addition, the target of a pointer might not even have a variable name. For example, consider:
char a;
char *ptr = &a + 5;
Now ptr is pointing somewhere that doesn't have anything to do with a (and in fact might be pointing outside of the memory allocated for your program and doing anything with that pointer could cause a segmentation fault).

It is not possible to get the name of the variables p or q point to if you compile and execute the program traditionally, because one of the things the compiler does is forget the name of the variables, keeping only addresses.
Depending on what you are trying to do, you may execute the program in a non-traditional execution environment where the names are preserved. For instance,
~ $ cat t.c
main(){
char name[20];
char *p=name;
int door_no;
int *q= & door_no;
}
~ $ frama-c -val t.c
[kernel] preprocessing with "gcc -C -E -I. t.c"
...
[value] ====== VALUES COMPUTED ======
[value] Values for function main:
p ∈ {{ &name ;}}
q ∈ {{ &door_no ;}}
__retres ∈ {0; }

Related

gcc and clang are giving different results

#include <stdio.h>
int main(int argc, char *argv[]){
int a;
int *b = &a;
a = 10;
printf("%d %d\n", a, *b);
int p = 20;
int *q;
*q = p;
printf("%d %d\n", p, *q);
int *t = NULL;
return 0;
}
The above program when compiled with gcc gives segmentation fault on execution. But when compiled with clang, it executes without giving segmentation fault. Can anybody give the reason? gcc version is 9.3.0 and clang version is 10.0.0. OS is ubuntu 20.04
Problem:
The problem does not stem from the compiler, it's in the code itself, specifically *q = p, when you dereference the pointer, i.e. use *, you are accessing the value stored in the pointer which is the address where it points to, in this case the code is invalid because there is no memory assigned to q, it points to nowhere (at least to nowhere we'd like it to point). You can't store anything in the memory pointed by it because it doesn't exist or is some random memory location given by some garbage value that may be stored in q.
Behavior explained:
Given the above, and knowing that the value stored in q can be anything, you can and should expect different results in different compilers, different versions of the same compiler, or even the same compiler in the same machine but in different executions of the same program, at some point it may even be pointing to where you want it to, in a one in a trillion chance, and the program would then give you the expected result, therefore the behavior of your program is undefined.
Fixing it:
As already stated q needs to be pointing to some valid memory location before you can store a value in that memory location. You can do that by either allocating memory and assigning it to q or make q point to an existing valid memory address, e.g.:
int p;
int *q;
q = &p; // now q points to p, i.e. its value is the address of p
Now you can do:
*q = 10; // stores 10 in the memory address pointed by(stored in) q, the address of p
// p is now 10
Or
int value = 20;
*q = value; // stores a copy of value in the address of the variable pointed by q, again p
// p is now 20
Extra:
Note that if you use extra warning flags like -Wall or -Wextra among others, the compiler is likely to warn you about faulty constructs like the one you have.
gcc warning flags manual
clang warning flags manual
I'm not an expert in compliers, but you are for sure triggering some Undefined Behaviour right here:
int *q;
*q=p;
printf("%d %d\n",p,*q);
You are dereferencing pointer q before initializing it.
Reasons why this segfaults (or rather, doesn't segfault) can be few. The q could point to any memory location, it could for example hold old value of b after it was popped from stack in case of Clang, thus writing into non-restricted memory.
Not sure what your original intentions were with this piece of code, though.
The reason is that anything can happen if you use a variable which has not been initialized. If you compile this program with warnings enabled you should get a warning like
t.c:10:5: warning: ‘q’ is used uninitialized in this function [-Wuninitialized]
*q = p;
~~~^~~
Before initialization, a variable can have any value which happens to be at the memory location where the variable is allocated. That's why the runtime behavior is unpredictable. The following picture illustrates the situation before the assignment of p:
Since we don't know where q point, we cannot dereferrence (follow) the pointer.
Can anybody give the reason?
The reason comes from the C language itself and how compilers were constructed.
First, the C language - your code invokes undefined behavior. Firstly, because using an uninitialized variable is undefined behavior, but obviously because you are applying * operator on an "invalid" pointer. Bottom line, there is undefined behavior.
Now, because there is undefined behavior, compilers can do what they want and generate code however they want. In short - there are no requirements.
Because of that, compiler writers do not care what compilers do in undefined behavior cases. Two compilers were constructed differently and act differently in this specific case when compiling this specific code. It was not deliberate - no one cares, so some random unrelated decisions in unrelated fields resulted in such behavior of both compilers.
The specific reasons why behaviors of both compilers are different, will come from inspecting the source code of both compilers. In this case, inspecting llvm with its documentation and gcc with gcc developer options will be helpful along the way.
The line *q=p; uses the value of q which is uninitialized; accessing an uninitialized variable is undefined behaviour, allowing the compilers to interpret both that line of code and anything preceding or following the line in any way at all.
It'd probably give different results for different levels of optimization as well.

Why does the execution of this basic program gives an error?

I don't really understand, why does the execution of this program give an error?
int main()
{
char *b;
*b='2';
printf("%c",*b);
return 0;
}
As it stands, b is uninitialized and thus may point to any arbitrary location. When you say *b =..., you are trying to write to some unspecified location, which (depending on what that location is) often causes an error (say a segfault). Perhaps you meant to declare b as a char instead of a pointer to one?
This looks like its taken straight from homework or a textbook. When you declare the char pointer b, it is not given a memory address (where it points to) by default, it just contains whatever was in the memory location beforehand. This means that if you attempt to work with the value (*b = '2' or printf) it will try to read this random information left over in memory as an address and look for a char at that address. This would cause a segmentation fault or if you're unlucky, it would grab garbage from the memory and use it as a char value.
The solution would be to create a char variable (char a) and set the pointer to the location of a (b = &a).
Hopefully this helps, and good luck on your studies.

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

Can an address be assigned to a variable in 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

Is it possible to find out the variable name, the pointer pointing to? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is it possible to find out the variable name, the pointer pointing to?
Is it Possible to get the name of array the pointer pointing too?
example:
char name[20];
char *p=name
int door_no;
int *q= & door_no
In the above example we are giving the base address of the array with the array name and pointer q pointing to door_no but what if, I have to know the name of the variable the array pointing too? what is the variable name pointer q is pointing too ? Is it possible I made tries and I came to a conclusion no its not possible but still Iam trying to get the solution. and what you think guys ? Is there any way to make it possible?
Short answer: No.
Long Answer:
In C variable names do not exist after compilation (everything is converted to either memory locations or register locations).
The compiler may potentially assign multiple variables to the same memory/register location if their lifespans of the two objects do not overlap. Thus the concept of variable names at runtime has no meaning (in the context of C)
No, it's not possible. Your pointer holds an address to a space in memory. The variable name is a name you have defined to mean that space in memory. So, you have somthing like this:
name -> mem space
q ------^
There is nothing linking q to name, and they don't go backwards. Both of them will get you to memory space, but you can't map back to them. Also, the program does not know that these happen to map to the same thing! The only reason you know is because you set it up to do so.
It is possible, but only within the scope of the original object.
You gave these examples (I've modified the formatting slightly):
char name[20];
char *p = name;
int door_no;
int *q = &door_no;
You can do comparisons equivalent to your assignments, thus:
if (p == name)
printf("p == name\n");
if (q == &door_no)
printf("q == &door_no\n");
This started as a comment, but then I realized it probably works better as an actual answer.
The short answer to the question as stated is, as others have already pointed out, no, you cannot map from a memory location to a variable name corresponding to that location.
Think about what would happen if it actually was possible to do something like what you want. Here is a thought experiment for you. I'm assuming C, but it should apply equally well in any language that supports pointers to arbitrary memory locations (including memory locations occupied by other variables).
Suppose that you start out with two pointers to an identical memory location:
char p[] = DUMMY;
char *q = &p;
Now, if you were to somehow de-dereference &q, you'd get p. Okay, that kinda-sorta works, in the theoretical sense. Now, add this:
char *r = &q;
Now, you have double indirection. If you try to figure out what names point to the same memory location as the name p, what is the result? If I recall the pointer syntax correct, you get *q and *(*r). How is the compiler going to tell you that, particularly at runtime?
Suppose that p[] is sufficiently large. For an arbitrary number n, replace the *q assignment by:
char *q = &p + n;
What is now the result of similarly de-dereferencing q? What would be the result in case q now points outside the bounds of p[]? (Okay, that latter could conceivably be just q, but then what's the point?)
Or, a practice which was quite common before the wide advent of GUIs. Try this (never mind the actual address).
short *videomemory = 0xB8000;
/* and then, at some later point... */
videomemory += 4;
Then, try to find the address corresponding to the value of videomemory (0xB8004, given the above). What is the result? In principle, the "array" videomemory[] extends indefinitely, even wrapping around (let's ignore memory protection for the moment), and thus anything will map into the memory "occupied" by videomemory[], only given a large enough array index.
It is not possible to get the name of the variables p or q point to if you compile and execute the program traditionally, because one of the things the compiler does is forget the name of the variables, keeping only addresses.
Depending on what you are trying to do, you may execute the program in a non-traditional execution environment where the names are preserved. For instance,
~ $ cat t.c
main(){
char name[20];
char *p=name;
int door_no;
int *q= & door_no;
}
~ $ frama-c -val t.c
[kernel] preprocessing with "gcc -C -E -I. t.c"
...
[value] ====== VALUES COMPUTED ======
[value] Values for function main:
p ∈ {{ &name ;}}
q ∈ {{ &door_no ;}}
__retres ∈ {0; }

Resources