Regarding double and triple pointers/double dimension arrays - c

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

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

Definition of double pointer

I m learning C programming and I have seen some code where folks use double pointers. I did some searching on stackoverflow from below but still have a teeny tiny question (Why use double pointer? or Why use pointers to pointers?)
In the code below, my question is I have not defined 'b' as **b. Now
when I try to do (*b) I`m getting a compile error. Isnt this *(*b) same as
*(address of c) because 'a' has address of 'c'.. Why do I need to define 'b' as **b to really get the value of 'c'?
#include <stdio.h>
int main()
{
int *a, *b, c;
c = 10;
a = &c;
b = &a;
printf("*a - %d\n *(*b): %d\n," , *a, *(*b));
return 0;
}
Help/explanation is really appreciated :)
EDIT : Thanks a lot guys for the explanation. Things are now clear :)
Here is a working code.
int main()
{
int *a, *b, c;
c=10;
a = &c;
b = a;
printf("*a - %d\n *(*b): %d\n,",*a, *(b));
return 0;
}
Pointers are aptly name: they "point" to locations in memory.
When you write *b, you tell the compiler that you are going to declaring a pointer of type integer so that it points to an integer.
When you use b = a, you tell the compiler that you are assigning the address of c to a as well. Actually, b is a pointer variable itself which is storing the address of an integer variable c. So, this way, you can assign the address of one variable to another pointer as well.
Now, Regarding your code,
int main()
{
int *a, **b, c; // just change it from *b to **b
c = 10;
a = &c;
b = &a;
printf("*a - %d\n *(*b): %d\n,",*a, *(*b));
return 0;
}
You need to specify the compiler that the pointer b is a pointer to a pointer variable by writing 2 *.When you write **b, you are telling the compiler that you are pointing to another pointer variable. Similarly, you can also have triple pointers and Quadrupled pointers as well.
Here is a link for your reference. http://www.c4learn.com/c-programming/c-double-pointer/
In your code, you have to do int **b; because:
a is a pointer-to-integer, since a = &c.
b is a pointer-to-(pointer-to-integer), since you wrote b = &a.
You can access the value of c using *b.. change your code littlebit..
#include <stdio.h>
int main()
{
int *a, *b, c;
c = 10;
a = &c;
b = a;
printf("*a :%d\n *b: %d\n,",*a, *b);
return 0;
}
*b,*a
defines that a and b are two pointer variable..
a=&c;
Assign the address of the variable c in pointer a.. & stand for address of operator.
b=a;
Copy the contains of a in b.. Now b also contain the address of c..
Print *a and *b.. *a and *b means contain of a and b. So *a and *b will print value of c..
You can also use **b.. **b means b is a pointer which stores address of another pointer variable..
In that case the code will be,
#include <stdio.h>
int main()
{
int *a, *b, c;
c = 10;
a = &c;
b = &a;
printf("*a :%d\n *b: %d\n,",*a, *(*b));
return 0;
}
a contains address of c and b contains address of a.. So, *a will print value of c..
As b is a double pointer we need *(*b) to access the contain of b.. *(*b) will also print the value of c..

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

address of pointer to C multi-dimension array

Question from code below:
#include <stdio.h>
int main(int argc,char *arg[]){
if (argc>2){
int m=atoi(arg[1]);
int n=atoi(arg[2]);
int a[m][n];
int (*p)[m][n]=&a;
printf("p : %p, *p : %p, **p : %p\n",p,*p,**p);
}
return 0;
}
Main Env: gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) x86-64
gcc main.c
./a.out 2 4
output:
p : 0xbfea7ef0, *p : 0xbfea7ef0, **p : 0xbfea7ef0
Question is why p == *p == **p. I think this may be because a is an array, kind of constant pointer which address is something specific, and this involves some implementation detail of gcc.
p is a pointer to an array with dimensions [m][n]. The value of that pointer is the address of a, so printing p gets you the address of a.
*p is an array with dimensions [m][n]. The "value" of this as a pointer is a pointer to the first element of the array, which is a[0]. This is the same address as a.
**p is an array with dimensions [n]. The value of this pointer is a pointer to the first element of the array, which is a[0][0]. This is the same address as a again.
The observed behaviour is the same for fixed-size arrays and variably-modified arrays:
#include <stdio.h>
int main(void)
{
enum { m = 3, n = 4 };
int a[m][n];
int (*p)[m][n] = &a;
printf("p : %p, *p : %p, **p : %p\n", p, *p, **p);
return(0);
}
On my machine, this produced:
p : 0x7fff6c542520, *p : 0x7fff6c542520, **p : 0x7fff6c542520
Of course, p is a pointer to a 2D array in both programs (and I shan't add the 'in both programs' qualifier again, even though it applies). When you print p, you get the address of the array that's assigned to it, which is the address of a. Because p is a pointer to a 2D array, *p 'is' the 2D array, but an array reference becomes a pointer to its first element in most situations, so *p is a pointer to a[0], which is the same memory location as a references. Similarly, **p 'is' a 1D array, but similarly, **p is a pointer to a[0][0], which is also the same memory location as a references. So, the three values are supposed to be the same, and the compiler gets it right.
That's not easy reading, but then, neither is the C that it is trying to explain.
Here's a minor variation on the original program which illustrates the sizes of the different objects pointed at by p, *p and **p:
#include <stdio.h>
int main(void)
{
enum { m = 3, n = 4 };
int a[m][n];
int (*p)[m][n]=&a;
printf("p+0 : %p, (*p)+0 : %p, (**p) + 0 : %p\n",
(void *)(p+0), (void *)((*p)+0), (void *)((**p)+0));
printf("p+1 : %p, (*p)+1 : %p, (**p) + 1 : %p\n",
(void *)(p+1), (void *)((*p)+1), (void *)((**p)+1));
return(0);
}
Strictly, the %p conversion specification should be given a void *; the casts here enforce that. The original code is, officially, a bit sloppy, though there are few machines where it would matter.
The output from this was:
p+0 : 0x7fff63453520, (*p)+0 : 0x7fff63453520, (**p) + 0 : 0x7fff63453520
p+1 : 0x7fff63453550, (*p)+1 : 0x7fff63453530, (**p) + 1 : 0x7fff63453524
Note how the sizes of the objects pointed at are different, as represented by the +1 version:
sizeof(*p) = 0x30
sizeof(**p) = 0x10
sizeof(***p) = 0x04

struct pointer manipulation

The Code used
#include<stdio.h>
struct st
{
char a;
short c;
int b;
};
struct st s1;
int main()
{
printf("%p %p \n",(&s1.b)-1, &s1);
}
If I print the address of &s1.b it prints 0x804a01c and &s1.b-2 prints 0x804a018
why it is printing same address 0x804a01c if i select &s1.b-1 ?
There's probably something wrong with your printing code.
#include <stdio.h>
struct st
{
char a;
short c;
int b;
};
struct st s1;
int main() {
printf("%p\n", (void*)(&s1.b));
printf("%p\n", (void*)(&s1.b - 1));
printf("%p\n", (void*)(&s1.b - 2));
}
Output:
0x403024
0x403020
0x40301c
Most likely you're printing it wrong:
#include <stdio.h>
struct st
{
char a;
short c;
int b;
};
struct st s;
int main(void)
{
printf("s: %p\n", (void *)&s);
printf("s.a: %p\n", (void *)&s.a);
printf("s.b: %p\n", (void *)&s.b);
printf("s.b-1: %p\n", (void *)(&s.b-1));
printf("s.b-2: %p\n", (void *)(&s.b-2));
return 0;
}
Prints for me:
s: 0x100001068
s.a: 0x100001068
s.b: 0x10000106c
s.b-1: 0x100001068
s.b-2: 0x100001064
Things to note:
Pointer to struct == pointer to struct's first element (guaranteed by the C standard),
I am printing the pointers with "%p" format string. "%p" needs void *, and since printf is a variadic function, I need to cast the arguments to printf to void * in this case.
What does the above program print for you?
Edit: based upon the actual code posted for printing that you posted later: you are not getting the same value for &s1.b and &s1.b-1. You are getting the same value for &s1.b-1 and &s1. The answer to that is: this happens because of chance. In your case, there is struct padding, and sizeof(short)+sizeof(char) happens to be ≤ sizeof(int). If you were on a machine where any of those assumptions were invalid, you wouldn't see that behavior. I am sure if you changed char or short to int in your code, &s1.b-1 would not equal &s1, when printed.
Finally, you should cast pointers to void * before printing:
printf("%p %p \n",(void *)((&s1.b)-1), (void *)&s1);
If the address of s1.b is 0x804a01c, then &s1.b-2 should be 0x804a014 (assuming that int is 4 bytes), not 0x804a018. Perhaps you made a mistake when you reported the address?
Thank you for posting your code. Now I see the issue. It is because of padding. To wit:
printf("sizeof(char): %d\n", sizeof(char));
printf("sizeof(short): %d\n", sizeof(short));
printf("sizeof(int): %d\n", sizeof(int));
printf("sizeof(struct st): %d\n", sizeof(struct st));
On my machine this prints
1
2
4
8
You might think, shouldn't sizeof(struct st) be 1 + 2 + 4 = 7? That's certainly a reasonable thought but because of alignment issues there is padding between a and c. Therefore, in memory, the struct looks like the following (relative to the first byte of the struct):
0x00000000: char a
0x00000001: padding
0x00000002: first byte of short c
0x00000003: second byte of short c
0x00000004: first byte of int b
0x00000005: second byte of int b
0x00000006: third byte of int b
0x00000007: fourth byte of int b
Consequently (relative to &s1):
&s1.b - 1 is ((long)&s1.b) - sizeof(int) = 4 - 4 = 0 = &s1
This is why both &s1 and &s1.b - 1 will print the same address. In particular if
&s1 = 0x804a01c
then
&s1.b = 0x804a01c + 0x00000004 = 0x804a020
and
&s1.b - 1 = 0x804a020 - 0x00000004 = 0x804a01c
and
&s1.b - 2 = 0x804a020 - 0x00000008 = 0x804a018
Note, finally, that this is implementation-specific behavior. This is not portable!

Resources