why below program taking memory difference to next location fix 12 in next memory location or its have some logic for char/float /int have diffrencet different -2 difference to next location
include
#include
int main () {
char var;
char *ptr;
char **pptr;
char ***ppptr;
char ****pppptr;
var = 'M';
/* take the address of var */
ptr = &var;
/* take the address of ptr using address of operator & */
pptr = &ptr;
ppptr=&pptr;
ppptr=&pptr;
ppptr=&pptr;
pppptr=&ppptr;
/* take the value using pptr */
printf("Value of var = %d\n", var );
printf("Value available at *ptr = %c....and address is %u\n", *ptr ,ptr);
printf("Value available at **pptr = %c....and address is %u\n", **pptr,pptr);
printf("Value available at ***ppptr = %c....and address is %u\n", ***ppptr ,ppptr);
printf("Value available at ****pppptr = %c....and address is %u\n", ****pppptr,pppptr);
getch();
return 0;
}
//out put
///-----------------------------------------------
Value of var = 77;
Value available at *ptr = M....and address is 11401207
Value available at **pptr = M....and address is 11401192 why differnceis 12 in memory locaton
Value available at ***ppptr = M....and address is 11401180
Value available at ****pppptr = M....and address is 11401168
You appear to be asking about why the address of ptr, as judged by printing the value of pptr using scanf field descriptor %u, appears to differ from the address of the next-declared local variable, pptr, by 12 bytes. And so on down the line for the other local variables, I presume.
In fact, as #SouravGhosh already described in his answer, the %u field descriptor does not correspond properly to pointer arguments, and therefore the effects of your scanf calls, including all aspects of the output, are undefined.
However, the actual results don't really matter for the purposes of the question. The C language provides no justification for assuming any particular ordering or difference between the addresses of any function's local variables. It is at the discretion of the compiler. There is therefore no general answer to the question.
If we hypothesize that the output you observed happens to accurately reflect the differences between the addresses of the local variables -- which is by no means certain -- then that would suggest that the compiler is intentionally leaving padding between the variables. It is entirely free to do so, for any purpose whatever. For example, the compiler might be trying to minimize the potential impact of off-by-one errors in code that accesses the local variables via the pointers to them.
First, a proper way to print pointers is with %p and with the pointer converted to void * when passed to printf, as in printf("%p\n", (void *) ptr);. Since you mention in a comment having used %P, differing from the %u shown in the question, I will presume that incorrect case is a typo, and you have reproduced the problem using %p with results similar to those shown in the question.
In that case, what is likely happening is that the compiler is storing the pointers ptr, pptr, ppptr, and pppptr at addresses that happen to be 12 bytes apart. Of course, it could store them merely four or eight bytes apart if pointers in your C implementation happened to be four or eight bytes in size. However, the compiler may be storing other things between the pointers, perhaps addresses of the strings you use in the printf statements or other incidental values. This makes me suspect that you compiled without optimization enabled. If you recompile with optimization, you will likely see different results.
In any case, a better explanation of the results would likely be had by asking the compiler to show the assembly code it generates (as by using the -S switch with GCC).
Using %u for printing pointer address results in undefined behavior.
Use %p format specifier and cast the argument to void *.
Related
As I understand it, all of the cases where C has to handle an address involve the use of a pointer. For example, the & operand creates a pointer to the program, instead of just giving the bare address as data (i.e it never gives the address without using a pointer first):
scanf("%d", &foo)
Or when using the & operand
int i; //a variable
int *p; //a variable that store adress
p = &i; //The & operator returns a pointer to its operand, and equals p to that pointer.
My question is: Is there a reason why C programs always have to use a pointer to manage addresses? Is there a case where C can handle a bare address (the numerical value of the address) on its own or with another method? Or is that completely impossible? (Being because of system architecture, memory allocation changing during and in each runtime, etc). And finally, would that be useful being that addresses change because of memory management? If that was the case, it would be a reason why pointers are always needed.
I'm trying to figure out if the use pointers is a must in C standardized languages. Not because I want to use something else, but because I want to know for sure that the only way to use addresses is with pointers, and just forget about everything else.
Edit: Since part of the question was answered in the comments of Eric Postpischil, Michał Marszałek, user3386109, Mike Holt and Gecko; I'll group those bits here: Yes, using bare adresses bear little to no use because of different factors (Pointers allow a number of operations, adresses may change each time the program is run, etc). As Michał Marszałek pointed out (No pun intended) scanf() uses a pointer because C can only work with copies, so a pointer is needed to change the variable used. i.e
int foo;
scanf("%d", foo) //Does nothing, since value can't be changed
scanf("%d", &foo) //Now foo can be changed, since we use it's address.
Finally, as Gecko mentioned, pointers are there to represent indirection, so that the compiler can make the difference between data and address.
John Bode covers most of those topics in it's answer, so I'll mark that one.
A pointer is an address (or, more properly, it’s an abstraction of an address). Pointers are how we deal with address values in C.
Outside of a few domains, a “bare address” value simply isn’t useful on its own. We’re less interested in the address than the object at that address. C requires us to use pointers in two situations:
When we want a function to write to a parameter
When we need to track dynamically allocated memory
In these cases, we don’t really care what the address value actually is; we just need it to access the object we’re interested in.
Yes, in the embedded world specific address values are meaningful. But you still use pointers to access those locations. Like I said above, a pointer is an address for our purposes.
C allows you to convert pointers to integers. The <stdint.h> header provides a uintptr_t type with the property that any pointer to void can be converted to uintptr_t and back, and the result will compare equal to the original pointer.
Per C 2018 6.3.2.3 6, the result of converting a pointer to an integer is implementation-defined. Non-normative note 69 says “The mapping functions for converting a pointer to an integer or an integer to a pointer are intended to be consistent with the addressing structure of the execution environment.”
Thus, on a machine where addresses are a simple numbering scheme, converting a pointer to a uintptr_t ought to give you the natural machine address, even though the standard does not require it. There are, however, environments where addresses are more complicated, and the result of converting a pointer to an integer may not be straightforward.
int i; //a variable
int *p; //a variable that store adres
i = 10; //now i is set to 10
p = &i; //now p is set to i address
*p = 20; //we set to 20 the given address
int tab[10]; // a table
p = tab; //set address
p++; //operate on address and move it to next element tab[1]
We can operate on address by pointers move forward or backwards. We can set and read from given address.
In C if we want get return values from functions we must use pointers. Or use return value from functions, but that way we can only get one value.
In C we don't have references therefore we must use pointers.
void fun(int j){
j = 10;
}
void fun2(int *j){
*j = 10;
}
int i;
i = 5; // now I is set to 5
fun(i);
//printf i will print 5
fun2(&i);
//printf I will print 10
I have the following program:
#include <stdio.h>
void func(char *str) {
int a = 4;
printf("\n str Address: 0x%8X\n", (unsigned int)&str);
printf("\n a Address: 0x%8X\n", (unsigned int)&a);
}
void main()
{
char c = 'y';
func(&c);
}
When I run the program, I get the following result:
str Address: 0x43570EB8
a Address: 0x43570ECC
My understanding is that the stack in Linux grows from high address to low address. Also str as an argument would be pushed first on the stack. If that is the case, why is str address lower than address for variable a ? Am I printing the addresses in an incorrect way ?
Most likely the parameter str is passed in a register. Normally, it would be used from that register and would never exist on the stack. Because your code takes the address of str, the compiler is forced to put it in memory somewhere so it can provide an address. It appears that the compiler created space for a on the stack first (or at least at a higher address), and then created space for str on the stack and copied the value from the register to the stack location.
You should not expect that inspecting the addresses of objects reveals or mirrors other aspects of a platform, such as its Application Binary Interface (which specifies, among other things, how function parameters are passed) or how stack is managed. A C implementation is free to rearrange things as long as the resulting program achieves the same observable behavior as defined by the C standard, and modern C implementations can make large and unexpected transformations while optimizing programs. Observable behavior includes defined outputs of a program but does not include any rules about the ordering of addresses of objects.
Incidentally, regarding your last question, yes, you are printing addresses incorrectly. To print an address, cast it to void * and print it with %p, not %X.
this is the code :
#include <stdio.h>
#include <stdlib.h>
int main() {
int a = 10;
int b = 20;
//printf("\n&a value %p", &a);
int* x = &b;
x = x + 1;
*x = 5;
printf("\nb value %d", b);
printf("\na value %d", a);
}
I want override a with b adress for test the c overflow but when I comment the line 5(printf fuction) I can't write five in a. While if I print the a adress I can write five in a.
Why?
Sorry for my english and thank you.
The reason this occurred is that all normal compilers store objects with automatic storage duration (objects declared inside a block that are not static or extern) on a stack. Your compiler “pushed” a onto the stack, which means it wrote a to the memory location where the stack pointer was pointing and then decremented the pointer. (Decrementing the pointer adds to the stack, because the stack grows in the direction of decreasing memory addresses. Stacks can be oriented in the other direction, but the behavior you observed strongly suggests your system uses the common direction of growing downward.) Then your compiler pushed b onto the stack. So b ended up at a memory address just below a.
When you took the address of b and added one, that produced the memory address where a is. When you used that address to assign 5, that value was written to where a is.
None of this behavior is defined by the C standard. It is a consequence of the particular compiler you used and the switches you compiled with.
You probably compiled with little or no optimization. With optimization turned on, many compilers would simplify the code by removing unnecessary steps (essentially replacing them with shortcuts), so that 20 and 10 are not actually stored on the stack. A possible result with optimization is that “20” and “10” are printed, and your assignment to *x has no effect. However, the C standard does not say what the behavior must be when you use *x in this way, so the results are determined only by the particular compiler you are using, along with the input switches you give it.
After x = x + 1;, x contains an address that you do not own. And by doing *x = 5; you are trying to write to some location that might not be accessible to you. Thus causing UB. Nothing more can be reasoned about.
I was experimenting with pointers. Look at this code:
#include <stdio.h>
int main() {
int numba = 1;
int *otherintptr = &numba;
printf("%d\n", otherintptr);
printf("%d\n", *otherintptr);
*otherintptr++;
printf("%d\n", otherintptr);
printf("%d\n", *otherintptr);
return 0;
}
The output is:
2358852
1
2358856
2358856
Now, I am well aware that (*otherintptr)++ would have incremented my int, but my question is not this.
After the increment, the memory location is correctly increased by 4 bytes, which is the size of an integer.
I'd like to know why the last printf instruction prints the memory location, while I am clearly asking to print the content of memory locations labelled 2358856 (I was expecting some dirty random content).
Note that the second printf statement prints the content of memory cell 2358852, (the integer 1) as expected.
What happens with these two lines
int numba = 1;
int *otherintptr = &numba;
due to the fact the C compiler will generate a sequential memory layout, otherintptr will initially point to the memory address corresponding to the numba variable. And this is relative to the stack frame allocated when main was called.
Now, the next position on the stack (actually the previous if we consider that the stack grows down on x86 based architectures) is occupied by the otherintptr variable. Incrementing otherintptr will make it point to itself, thus you see the same value.
To exemplify, let's assume that the stack for main begins at the 0x20 offset in memory:
0x20: 0x1 #numba variable
0x24: 0x20 #otherintptr variable pointing to numa
After executing the otherintptr++ instruction, the memory layout will look like this:
0x20: 0x1 #numba variable
0x24: 0x24 #otherintptr variable now pointing to itself
This is why the second printf's have the same output.
When you did otherintptr++, you accidentally made otherintptr to point to otherintptr, i.e. to itself. otherintptr just happened to be stored in memory immediately after your numba.
In any case, you got lucky on several occasions here. It is illegal to use an int * pointer to access something that is not an int and not compatible with int. It is illegal to use %d to print pointer values.
I suppose you wanted to increment the integer otherpointer points to (numba). However, you incremented actually the pointer, as ++ binds stronger than *
see here.
So otherpointer pointed past the variable. And as there is no valid variable, dereferencing the pointer is undefined behaviour. Thus, anything can happen and you just were lucky the program did not crash. It just happend by chance otherpointer itself resided at that address.
I just executed this code example:
int *i = (int*) malloc( sizeof(int) );
printf( "%p, %p\n", &i , i );
and this is what I got:
0x7fff38fed6a8, 0x10f7010
So I wonder why is the second address shorter than the first one?
i is on the stack, while the chunk of memory it points to is in the heap. On your platform these are two very different areas of memory and it just so happens the heap addess is relatively low, numerically, so it has a lot of leading zeroes which are not shown, i.e.
&i = 0x7fff38fed6a8; // stack
i = 0x0000010f7010; // heap
i is an address on the heap, while &i is an address on the stack. The heap and stack occupy different address ranges, so you see different numbers.
The pointers aren't actually different lengths: the shorter one is preceded by zeroes. You are probably running this on a 64-bit machine, so each pointer has 64 bits (16 hex digits).
It is not shorter, just number is smaller. Pointer &i is on stack and i is on heap.
There is no requirement that the %p formatting specifier pads the output to any fixed length. So you can't deduce any information about the in-memory "length" of an address from the printed representation. For instance, if you do this:
const void *nada = NULL;
printf("NULL is at %p\n", nada);
You might well see something like this:
NULL is at 0x0
Of course, this doesn't mean that the void * type is magically occupying only 4 bits when the value is NULL, it simply means that when the pointer value was converted to string, leading zeros were omitted.
UPDATE: Mis-read the question's code, I deleted the irrelevant text.
In addition to the other answers:
Since you didn't include <stdlib.h> there is a good chance that the compiler incorrectly assumes that malloc returns int rather than void*. This is a possibly severe bug, which you have hidden away with the typecast of malloc's return value. Read this and this.
If int has a different width than the address bus on your specific system, for example on many 16-bit or 64-bit CPUs, you will get incorrect results.