Memory addresses of stack - c

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
struct s1 {
char *z;
int i;
struct s1 *p;
};
struct s1 *ptr;
static struct s1 a[] = {
{"Nagpur", 1, a + 1},
{"Raipur", 2, a + 2},
{"Kanpur", 3, a}
};
ptr = a;
printf("%p\n", a[0]);
printf("%p\n", a[1]);
printf("%p\n", a[2]);
printf("%p\n", ptr);
printf("%p\n", a[2].p);
printf("%p\n", a[1].p->p);
printf("%p\n", a);
return EXIT_SUCCESS;
}
Whenever we have an array, suppose we call it a[10], then the address of a or a[0] are equal. But in the above case, the address of a and that of a[0] is different. I can't figure out why?

What you're passing to printf() here is the structure itself, not a pointer to it:
printf("%p\n", a[0]);
The behavior of this code is poorly defined. (In practice, it will typically end up printing the first element of the structure, but this may not be consistent.) What you probably want is:
printf("%p\n", &a[0]);
^

If you had compiled with warnings enabled (e.g. gcc -Wall -Werror), you would see that this line:
printf("%p\n", a[0]);
is invalid:
ptr.c:20:5: error: format ‘%p’ expects argument of type ‘void *’, but
argument 2 has type ‘struct s1’ [-Werror=format=]
printf("%p\n", a[0]);
^
You're taking the 0th element of that structure, or in other words, dereferencing a, and passing a struct s1 by value to printf, who is doing like you said, and interpreting it as a pointer.
If you instead take the address of the first element of the array, you'll see that they are indeed, at the same address:
printf("%p\n", &a[0]);

The reason why both are different is when you print a, its just reference, whereas a[0] is used to de-reference. Try printf("%p\n",&a[0]).

the printf() calls with the a[x] parameter will not print addresses but rather the contents of that offset. This line segment: 'then the address of a or a[0] are equal' is not true. However, then the address of a and the address of a[0] are equal is true. The '%p' format converter is only for addresses. so the code needs to use addresses, not the contents.
suggest using something like:
printf("%p\n", &a[0]);
printf("%p\n", &a[1]);
printf("%p\n", &a[2]);
printf("%p\n", ptr);
printf("%p\n", a[2].p);
printf("%p\n", a[1].p->p);
printf("%p\n", a);

you are assigning addresses of strings (e.g. "nagpur") char pointer. these strings will be present in code section. so "z" will be having addresses of those strings and you are trying to print those by printing a[0]. you should print &a[0] instead. a[0] is similar operation to *(a+0). so if you want to print its address you should use & operator.

Related

If int array variable return address of first element of int array then why char array variable not return address of first element?

Here, i attached code image
how it treat in char array?
If image is not clear, then refere this code
#include <stdio.h>
int main() {
char c[3] = {'s', 'a', 'h'};
int a[3] = {1, 2, 3};
printf("%c\n", c);
printf("%d\n", a);
return 0;
}
I tried this code but not getting expected result. Might be possible I am wrong expecting but want to know why it happening.
In this code snippet
char c[3] = {'s', 'a', 'h'};
int a[3] = {1, 2, 3};
printf("%c\n", c);
printf("%d\n", a);
the array designators c and a used in the calls of printf are implicitly converted to pointers to their first elements of the types char * and int *. In fact you have
printf("%c\n", &c[0]);
printf("%d\n", &a[0]);
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array
object has register storage class, the behavior is undefined.
But the conversion specifiers c and d expect objects of the type char and int correspondingly.
You have to write instead
printf("%c\n", *c);
printf("%d\n", *a);
That is the same as
printf("%c\n", c[0]);
printf("%d\n", a[0]);
If you want to output addresses of the first elements of the arrays (that is the same values of the addresses of the whole arrays) you need to use conversion specifier p. For example
printf("%p\n", ( void * )c);
printf("%p\n", ( void * )a);
If you want to output addresses as integers you need to include headers <inttypes.h> and <stdint.h> (the last is already included in the first header) casting pointers either to the type intptr_t or uintptr_t and use appropriate macros. Here is a demonstration program.
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main( void )
{
char c[] = { 's', 'a', 'h' };
int a[] = { 1, 2, 3 };
printf( "address of c is %p\n", ( void * )c );
printf( "address of c as integer is %" PRIuPTR "\n", ( uintptr_t )c );
printf( "address of a is %p\n", ( void * )a );
printf( "address of a as integer is %" PRIuPTR "\n", ( uintptr_t )a );
}
The program output might look like
address of c is 00C4F8FC
address of c as integer is 12908796
address of a is 00C4F8E8
address of a as integer is 12908776
The main reason you can't get expected result is the following.
printf("%c\n", c);
Here c is the address type not string. If you want to print the first value of char array, you should use *c, because c is the address of the first entry of an array, not the value.
But if you want to print address, print type should be %d or something else, not %c.
This is why printf("%d\n", a) works.
So if you want to print values,
printf("%d\n", *a);
printf("%c\n", *c);
And if you want to print addresses,
printf("%d\n", a);
printf("%d\n", c);

Passing array of pointers to a function accepting 2d array

I have the following code in C
#include <stdio.h>
char *gstr[] = { "Hello", "World" };
void func(char str[][8]) {
printf("%p\n", (void *)str);
printf("%p\n", (void *)(str + 1));
printf("%s\n", *(str + 1));
}
int main(void) {
printf("%p\n", (void *)gstr);
printf("%p\n", (void *)(gstr + 1));
printf("%s\n", *(gstr + 1));
printf("Calling Function\n");
func(gstr);
return 0;
}
The following is the output
0x556f11ddd010
0x556f11ddd018
World
Calling Function
0x556f11ddd010
0x556f11ddd018
$��oU
I cannot understand why printf("%s\n", *(str+1)); in the function func does not print the string world.
char *gstr[] = {"Hello", "World"}; declares gstr to be an array of pointers to char.
By itself, char str[][8] declares str to be an array of arrays of eight char. However, as a function parameter, it is automatically adjusted from an array to a pointer: It declares str to be a pointer to an array of eight char.
A pointer to an array is different from an array of pointers.
Your compiler should have warned you that the type of gstr in func(gstr) is incompatible with the type of the parameter in void func(char str[][8]). Pay attention to the messages from your compiler.
To pass gstr to func correctly, change the declaration of func to func(char *str[]) or the equivalent func(char **str).
func(gstr) passes the address of the first element of gstr to the function. Since gstr is an array of pointers, the address of its first element is the address of a pointer (that being a pointer to the first character of "Hello").
In func, the function expects a pointer to an array of eight char. If it uses the address it is given for that, it is pointing to a pointer instead of an array of eight char. Passing that to printf attempts to print the bytes representing the pointer as if they were a string of characters.
You can compile the code below to see the output.
#include <stdio.h>
char *gstr[] = {"Hello", "World"};
void func(char str[][8]) {
printf("%p\n", (void*) str);
printf("%p\n", (void*) *str);
printf("%p\n", (void*) (str+1));
printf("%p\n", (void*) *(str+1));
printf("%s\n", *(str+1));
}
int main(void) {
printf("%p\n", (void *) gstr);
printf("%p\n", (void *) *gstr);
printf("%p\n", (void*) (gstr+1));
printf("%p\n", (void*) *(gstr+1));
printf("%s\n", *(gstr+1));
printf("Calling Function\n");
func(gstr);
return 0;
}
0x100402010
0x100403000
0x100402018
0x100403006
World
Calling Function
0x100402010
0x100402010
0x100402018
0x100402018
0#
The compiler know that gstr is an array of pointers, so that in function main, the object at gstr + 1 will be interpreted as char* and you get the expected result.
However in function func, the bytes at str + 1 will be interpreted as char [8], and you know it will return the first address of this object which is str+1

Unexpected behaviour found while dealing with a pointer to an array

Look at the code given below:
#include<stdio.h>
int main()
{
int (*p)[3];
int a[3]={10,11,12};
p=&a;
printf("%d\n", *p[0]);
printf("%d\n", *p[1]);
printf("%d\n", *p[2]);
return 0;
}
printf("%d\n", *p[0]); prints 10 which is expected.
But printf("%d\n", *p[1]); doesn't print 11.
And
printf("%d\n", *p[2]); doesn't print 12.
Why? What's the reason behind this?
Operator precedence. [] has higher precedence than *, so when you write *p[0] it is the same as (*(*(p + 0))) - you do pointer arithmetic on an array pointer.
Meaning that for example p[1] gives you the address of p + 3*sizeof(int) bytes, which is accessing the array out of bounds.
Correct code should be:
printf("%d\n", (*p)[0]);
printf("%d\n", (*p)[1]);
printf("%d\n", (*p)[2]);
*p[k] is *(p[k]), not (*p)[k].
That you get the expected result for *p[0] can be explained by its being the same as p[0][0], and it doesn't matter which order you put the zeros in.
p[1][0] (*p[1]), however, is not the same as p[0][1] ((*p)[1]).
(It's even undefined, since p[1] does not exist.)
int (*p)[3]; is an array of pointers to int.
int a[3]={10,11,12}; is an array of int. Arrays and pointers share a lot of properties. You can use array notation for pointers for example.
Lets take a normal pointer int *p = a which is the same as int *p = &a[0]. Now the pointer points to the first element of the array. And you can use it the same way as the array.
printf("%d\n", p[0]); //10
printf("%d\n", p[1]); //11
printf("%d\n", p[2]); //12
What you did was getting the address of the array-"pointer" this yields the address of the first element of the array. Because &a == a
This gets written to the first element of your pointer array leaving you with
p[0] == a
p[1] == unknown
p[2] == unknown
by doing *p[0] you get the first element of p (p[0]) and dereference it *.
This is the same as *a or a[0].
But by doing *p[1] you get to an unkown memory location(p[1]) and derefence it *. This is undefined behaviour.

Regarding double and triple pointers/double dimension arrays

So, i was playing with C pointers and pointer arithmetic since i'm not entirely comfortable with them. I came up with this code.
char* a[5] = { "Hi", "My", "Name", "Is" , "Dennis"};
char** aPtr = a; // This is acceptable because 'a' is double pointer
char*** aPtr2 = &aPtr; // This is also acceptable because they are triple pointers
//char ***aPtr2 = &a // This is not acceptable according to gcc 4.8.3, why ?
//This is the rest of the code, the side notes are only for checking
printf("%s\n",a[0]); //Prints Hi
printf("%s\n",a[1]); //Prints My
printf("%s\n",a[2]); //Prints Name
printf("%s\n",a[3]); //Prints Is
printf("%s\n",a[4]); //Prints Dennis
printf("%s\n",*(a+0)); //Prints Hi
printf("%s\n",*(a+1)); //Prints My
printf("%s\n",*(a+2)); //Prints Name
printf("%s\n",*(a+3)); //Prints Is
printf("%s\n",*(a+4)); //Prints Dennis
printf("%s\n",*(*(aPtr2) +0)); //Prints Hi
printf("%s\n",*(*(aPtr2) +1)); //Prints My // ap = a, *ap = *a, *(ap)+1 = *a+1 ?
printf("%s\n",*(*(aPtr2) +2)); //Prints Name
printf("%s\n",*(*(aPtr2) +3)); //Prints Is
printf("%s\n",*(*(aPtr2) +4)); //Prints Dennis
char*** aPtr2 = &a is not acceptable according to gcc 4.8.3, why?
Sorry forgot to add compiler warning:
warning: initialization from incompatible pointer type [enabled by default]
It maybe unclear what I'm trying to say, so I had to add this links:
This is the code that works: http://ideone.com/4ePj4h. (line 7. commented out)
This is the code that does not work: http://ideone.com/KMG7OS. (line 6. commented out)
Notice the commented out lines.
a is the address of a buffer of 5 ptrs and is immutable (i.e. its a fixed ptr). If you allowed
char ***aPtr2 = &a;
then
*aPtr2 = &a[3];
would actually modify the address a (which is verboten).
This comes from the way C treats arrays and addresses:
int a[5];
a is of the type int * const, true, meaning you can use it where a pointer is expected. However, on the stack the space for the pointer isn't allocated, only the space for the five ints. Meaning a is the same as &a[0]. This is all expected, but here comes the weird part:
a is the same as &a. This is because the pointer isn't stored anywhere, you can't get it's address. But instead of failing the compile, the C standard just says that they are the same, so some arithmetic will work.
However, since you are doing char ***aPtr2 = &a;, you are effectively doing char ***aPtr2 = a;, which is why you get a segfault. It is only a double pointer, not a triple one.
You can inspect all the values in the debugger to see it more clearly, or run a program such as:
#include <stdio.h>
int main(void)
{
char *a[5] = { "Hi", "My", "Name", "Is" , "Dennis"};
char **aPtr = a;
char ***aPtr2 = &aPtr;
char ***aPtr3 = &a;
printf("%p %c\n", a, *a);
printf("%p %p %c\n", aPtr, *aPtr, **aPtr);
printf("%p %p %p %c\n", aPtr2, *aPtr2, **aPtr2, ***aPtr2);
printf("%p %p %c\n", aPtr3, *aPtr3, **aPtr3);
return 0;
}
which produces the output:
0xfff65578 H
0xfff65578 0x8048648 H
0xfff65574 0xfff65578 0x8048648 H
0xfff65578 0x8048648 H
EDIT: Another interesting thing is the function pointers are treated in the same fashion. &func is the same as func.
int add(int a, int b) { return a + b; }
typedef int (*PFUNC)(int, int);
PFUNC p1 = add;
PFUNC p2 = &add;
if (p1 == p2)
printf("Huh. %d, %d\n", (*p1)(1,2), p2(3, 4)); // the dereference is also optional

What is the meaning of printf("%p", int 1)?

I'm trying to understand the difference between int a and int *a, my first step was to see the value I could get by printi %p of an int a. Of course the compiler shows warnings, but does complete the job for the following code.
#include <stdio.h>
int main() {
int a;
printf("a - declared");
printf("int a = [%d]\n", a); // example - 1745899614
printf("int a pointer = [%p]\n", a); // example - 0x6810505e
a = 10;
printf("a - initialized to value of 10\n");
printf("int a = [%d]\n", a); // exmaple - 10
printf("int a pointer = [%p]\n", a); // example - 0xa
return 0;
}
And as I've mentioned in the source code, I do get a somewhat satisfactory result of 0xa which is equal to 10 in hexadecimal for the value of %p of an int a. But is it actually the case that int points to to that address, or is this just the compiler trying to make sense of %p in such a case?
Where is the memory allocated for ints? How do I test for that?
To print the address of an object named a, use:
printf("The address of a is %p.\n", (void *) &a);
Merely using %p does not tell printf to print the address of the object you use as the argument. You must use the “address of” operator, &, to take the address. Otherwise, you are passing the value of a to printf, not the address of a.
Additionally, it is proper to convert the address to void *, as shown above, because the %p specifier expects a pointer to void. Other types of pointers often work (or appear to work) in many C implementations, but the technical requirement is that a pointer to void be passed.
I imagine the formater ( in printf ), is just interpreting the memory as it is told to. So yeah, "%p" is for pointer, but you gave it an int. You wanted to give it the address of a:
printf( "%p", &a );
for the whole shabang:
int a = 10;
int *b = &a;
printf("value of a: %d\n", a );
printf("location of a: %p\n", &a );
printf("value of b: %p\n", b );
printf("location of b: %p\n", &b );
printf("dereference b: %d\n", *b );
But is it actually the case that int points to to that address, or is
this just the compiler trying to make sense of %p in such a case?
It's the latter. Compiler tries to interpret the integer as a pointer. When you print the value of a using %p compiler finds that the type of a is int and warns you that it's not a pointer.
To print the address of a use:
printf("int a pointer = [%p]\n", (void*)&a);
If a is a pointer (e..g int *a;) then you need to initialize it with a valid address and then you can print:
printf("int a pointer = [%p]\n", (void*)a);
%p is merely a way to tell printf to print your value as an address memory. You're passing the value of 10to it (the value of a) and you get printed this value in the hexadecimal notation 0xa. There is no special interpretation, it is just a formatting option.
If you want the value of the a's address memory printed you can simply do printf("%p", &a);. &a is the address of a.
Or if you want to use a pointer:
int* p;
p = &a;
printf("%p", p); //Prints the p value, that is the a address. Equivalent to printf("%p", &a).

Resources