I was just goofing around on C, as I had just learned more about pointers. But my main confusing point was about addresses, I was just checking out random variable addresses and here's what I found.
#include<stdio.h>
#include<conio.h>
int main()
{
int x=5;
int y=4;
int z=8;
printf("%p\n",&x);
printf("%p\n",&y);
printf("%p\n",&z);
}
This code shows 3 different addresses, which is what to be expected. If I only have one printf statement, like this
printf("%p\n",&x);
It will show me one of the addresses, which is expected as well. But, if I remove the variable 'x', and use another variable like 'y', or 'z', it will show me the exact same address that 'x' had. How is that possible?
So basically, when you check all the variables' addresses in the same code, each will have a different address. If you check each of them separately, they will have the exact same address.
PS: This only happens for integers and floats, I tried the same with char and each variable gave a separate address.
The compiler is optimizing away unused variables in your code. This is dead code elimination.
So when you have code like this
int main()
{
int x=5;
int y=4;
int z=8;
printf("%p\n",&z);
}
The compiler can tell that you never use x or y, and therefore can remove that code from the compiled object. This makes your generated code faster and generates smaller object sizes.
Probably, the compiler is eliminating the unused variables. Hence, only the ones you are calling to print are getting created.
"But, if I remove the variable 'x', and use another variable like 'y', or 'z', it will show me the exact same address that 'x' had."
This has nothing to do with optimizing away as other answers suggest, though the result is the same: in your second test you did not declare your variable. Your program then looks like
int main()
{
//int x=5; // commented out
int y=4;
int z=8;
//printf("%p\n",&x); // commented out
printf("%p\n",&y);
printf("%p\n",&z);
}
For each variable, the compiler reserves space (here: on the stack) and this compiler apparently does that in the order it encounters your declarations (nearly all compilers do that). x no longer being declared, all following variables just move up in the address space.
Note that it does that for all variables, also char variables. But for char variables you often give a size. Consider:
char s1[10];
char s2[10];
char s3[10];
and:
//char s1[10]; // commented out
char s2[10];
char s3[10];
s2 of the second example will have the same adress as s1 in rhe first example because all these s variables are the same size. Were they different sizes you would see different addresses but yoy can calculate these differences from their sizes. (Note: "padding" can come into play here, where the compiler allocates slightly more then you declare so the next variable starts on a 4 byte/8 byte boundary (4: 32 bit compilation; 8: 64 bit compilation).
Related
We have a c program with a lot of files and we are wondering one specific thing.
We are compiling it with C51.
If, lets say in one of the files, I declare a few variables like:
unsigned char xdata a;
unsigned char xdata b;
...
//etc
unsigned char xdata z;
Will their addresses be incrementing and in the same order? as they are declared?
I realize that incrementing addresses can be achieved using arrays or structs or that I can assign fixed addresses of choice but that is not the question.
Will their addresses be incrementing and in the same order? as they are declared?
No, you can't know or assume anything about this. They may be allocated in any order on the stack, or in registers, or not allocated at all. The only time when allocation order is guaranteed is when declaring arrays and structs.
In addition, you can't use pointer arithmetic on anything that's not an array, or you risk running into various subtle undefined behavior bugs.
I am currently working on a personal AVR project and wrote a function for transmitting a double to my serial LCD screen using UART. For this, I convert a double into a char array and then transmit it char by char, serially.
What confuses me is what the length of the char buffer array has to be. The length of the array does not seem to correspond to the size of a double. Funnily enough, I can set the the length of the array to 0, and it will still work, like this:
void USART_Transmit_Double(double doubleNumber) {
char aNumberAsString[0];
dtostrf(doubleNumber, 3, 0, aNumberAsString);
USART_Transmit_String(aNumberAsString);
}
Here I am printing number 1234 in the main loop and it appears on my LCD just fine. If I change the precision to 1 however, the entire thing goes haywire.
I tested the same function on my Arduino and keep getting completely different results, on it each character seems to correspond to each element of the array, so if I wanted to print 1234.2, I would have to set the buffer length to 6.
So what's going on here?
You are running into undefined behavior. In particular, in this link, the phrase: Examples of undefined behavior are memory accesses outside of array bounds,... would likely apply to your described scenario. It may work a thousand times if the memory you are attempting to access (but do not own) does not happen to violate another variable's memory space. The first time it does, your program will crash.
The following statement, although legal, creates a useless variable, and is likely the reason you are seeing odd results:
char aNumberAsString[0];
Addressing your comment:
You may be confusing the index value necessary to create a buffer containing a single value, with the index value necessary to access that value once the variable is created. i.e.
char aNumberAsString[1] = 'A'; //creates an array of 1 char ([1])
will create a variable that can contain a single char value.
char value = aNumberAsString[0]; // accesses the only value in array ([0])
EXAMPLE:
See an example of how to use the dtostrf function here.
Note the size of the variables this example is using:
static float f_val = 123.6794;
static char outstr[15];
to support the following call:
dtostrf(f_val,7, 3, outstr);
Which produces the following output:
123.679
I'm in a sophomore C class and this project is about dealing with pointers and designing a memory dump function. So I've been able to struggle through the pointers and got a beginning and ending address to dump, even bitmasked it, and I wanted to initialize a char array with the beginning memory address. I initialize it with the same variable storing my masked beginning address but when I print the array, it contains a different memory address. Here's the function:
void memDump(void *base, int bytes)
{
unsigned char *begin;
begin = base;//beginning of range of memory
unsigned char *end;// ending range of memory
end = base + bytes;
int a, b;
long long int d=base;
d=d&0xFFFFF0; //trying to bitmask
long long int e=end;
e = e&0xFFFF0; //masked off the beginning and ending range
char c[16]={d}; //loop variables
printf("%x", c);
for (a=begin; a<=end; a+=16)
{
printf("\n%016X\n", d);
printf("%016X\n", a);
printf("%016X", e);
}
}
Sorry guys, i can't find something similar and this is my last resort. Thanks!
Update: Thanks for the insight everyone, reading some more about C and some articles on how to debug helped me out.
You cannot "initialize a char array" with some "memory address." A char array can only be initialized with characters.
Stackoverflow is not about doing your homework for you, so I will give you some advice, and then you can try implementing it. If you cannot put the advice into code, then you do not deserve to turn in a completed assignment.
First of all, once you have bitmasked your "d", you need to store it back into "begin", so that you have a pointer from which you can start reading bytes to dump.
This instruction:
printf( "%08p ", begin );
Will render the hexadecimal representation of your "begin" address in 8 characters, followed by a space. This is how you need to begin each row of your memory dump.
The instruction:
printf( "%02x ", *(begin++) );
gets the byte pointed by "begin", and renders the hexadecimal representation of that byte in two characters, followed by a space. It then increments "begin", to point to the next byte. You need to do this 8 or 16 times, depending on how wide you want your memory dump to be, then do a printf( "\n" ) to move to the next line.
Then you need to keep repeating the above until your "begin" has exceeded your "end". (So, you are looking at an outer loop, for each row, and an inner loop, for each byte within the row.)
I hope this helps.
As #Jean-FrançoisFabre observed,
char c[16]={d};
probably does not do what you think it does. That is, unless what you think it does is convert the long long int value stored in d to type char (producing an implementation-defined result drawn from a much smaller range than that of d itself), initializing the first element of array c with that value, and initializing the other fifteen with 0. I can't imagine what you would want to do with the result, but since you actually don't do anything with it, that's probably moot.
As I observed myself,
printf("%x", c);
also probably does not do what you think it does. Indeed, you cannot rely on it to do any particular thing, because its behavior is undefined. You are passing a pointer to the first element of c as the second argument, but a value of type unsigned int will be expected instead (based on the format). In any case, this neither "print[s] the array" nor tells you anything about what it contains.
I suspect that what you actually had in mind was to declare c as an array whose address -- not contents -- is that designated by base, truncated to a 16-byte-aligned address. You cannot do that, because you cannot specify the address of any variable you declare, but you can declare c as a pointer, like this:
unsigned char *c = d;
(Oh no, more pointers!) There's some implementation-dependency there, but it probably has the result I think you want. Or if you want to be really clever, you might do this:
unsigned char (*c16)[16] = d;
That declares c16 as a pointer to an array of 16 unsigned char. It's as close as you can get to declaring an array at an address specified by you. I suspect you'll find it easier to work with the other declaration, however.
If you want to print the contents of the memory to which such a pointer points (as a "memory dump" function seems wont to do) then you'll need to do a little more work. The standard library's formatted I/O functions do not provide directly for printing arrays (for good reasons that I'll not go into here), except C strings, and you do not appear to want to print the data as a C string. Do, however, consider this call, and how you might modify it for or adapt it to your purpose (assuming my above declaration for c):
printf("%02x", *c);
#include<stdio.h>
#include<conio.h>
int main(){
char i;
int c;
scanf("%i",&c);
scanf("%c",&i);// catch the new line or character introduced before x number
printf("%i",i);// value of that character
getch();
return(0);
}
The program will behave in the same way with the next variable declarations instead of the above variable declaration:
this:
int c;
int *x;
int i;
or this:
int *x;
int c;
int i;
And only this way: c variable and a x pointer before the i variable.
I know that those last declarations haven't sense, the int i instead of char i, and an added pointer that isn't even needed.
But this have been occurred accidentally and im wondering if it's only an a coincidence.
The order in which you declare your variables should make no difference at all, assuming there's nothing wrong with the rest of your code. The order of declaration needn't have anything at all to do with the way they're laid out in memory. And even if it did, you refer to variables by name; as long as your code is correct, a reference to i is a reference to i, and the compiler will generate whatever code is needed to access the variable correctly.
Now if you do this:
int i;
scanf("%c", &i);
then you're doing something wrong. scanf with a "%i" format requires a char* argument, which points to the char object into which the value will be stored. You're giving it an int* rather than a char*. As a result, your program's behavior is undefined; the language standard says nothing about how it will behave.
So why does it appear to work correctly? What's probably happening is that scanf treats the address of the int object i as if it were a pointer to a char. It will probably point to the first byte of the representation of i; for example, i might be 32 bits, and the pointer will point to the first 8 of those bits. (They could be the high-order or low-order bits, depending on the system.)
Now when you print the value of i:
printf("%d\n", i);
the contents of i are, for example, 1 byte consisting of whatever character you just read into it, and 3 bytes of garbage. Those 3 garbage bytes may well all be zeros, but they could be anything. If the garbage bytes happen to be 0, and the first byte happens to be the high-order byte (i.e., you're on a big-endian machine), then you're likely to get the "correct" output.
But don't do that. Since the behavior is undefined, it can work "correctly" for years, and then fail spectacularly at the worst possible moment.
The lesson here is that C tends to assume that you know what you're doing. There are a lot of constructs that have undefined behavior, which means that they're invalid, but neither the compiler nor the runtime system is required to tell you that there's a problem. In C, more than in most other languages, it's up to you as a programmer to get things right. The compiler (and other tools) will tell you about some errors, but not all of them.
And in the presence of undefined behavior, the order in which you declare your variables can make a difference. For example, if you write code that reads or writes past the end of a variable, it can matter what happens to be stored there. But don't be tempted to shuffle your declarations around until the program works. Get rid of the undefined behavior so the order doesn't matter.
The solution: Don't make mistakes in the first place. (Of course that's much easier said than done.)
And naming conventions can be helpful. If you had called your char variable c, and your int variable i, rather than vice versa, it would have been easier to keep track of which is which.
But c is a reasonable name for an int variable used to hold input character values -- not for scanf, but for getchar(), as in:
int c;
while ((c = getchar()) != EOF) {
/* ... */
}
The function expects a sequence of references as additional arguments, each one pointing to an object of the type specified by their corresponding %-tag within the format string, in the same order. Read about scanf
These can additionally help you:
I don't understand why I can't get three inputs in c
scanf() leaves the new line char in buffer?
Regarding the last portion of your question, the number of bits of int is always more than char, so it won't cause a problem.
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; }