array of pointers - c

Consider the following code:
#include <stdio.h>
int main()
{
static int a[]={0,1,2,3,4};
int *p[]={a,a+1,a+2,a+3}; /* clear up to this extent */
printf(("%u\n%u\n%u",p,*p,*(*p))); /* how does this statement work? */
return 0;
}
Also is it necessary to get the value of addresses through %u,or we can use %d also?

Okay, you've created an array of integers and populated it with the integers from 0 to 4. Then you created a 4 element array of pointers to integers, and initialized it so its four elements point to the first four elements of a. So far, so good.
Then the printf is very strange. printf is passed a single argument, namely ("%u\n%u\n%u",p,p,(*p)). This is a comma-expression which means that the comma-separated expressions will be calculated in turn, and only the last one returned. Since the very first thing is a literal, and not an expression, I'd expect it to generate an error. However, without the extraneous parentheses, you have:
printf("%u\n%u\n%u\n",p, *p, *(*p));
This is legal. Three values are passed to printf, interpreted as unsigned integers (which actually only works on some systems, since what you are actually passing in are pointers in the first two cases, and they aren't guarateed to be the same size as unsigned ints) and printed.
Those values are p, *p and **p. p is an array, and so the value of p is the address of the array. *p is what p points to, which are the values of the array. *p is the first value, *(p+1) is the second value, etc. Now *p is the value stored in p[0] which is the address of a[0], so another address is printed. The third argument is **p which is the value stored at (*p), or a[0], which is 0

Do you have an extra pair of parens in your printf statement?
Anyway, you can think of this statement:
printf("%u\n%u\n%u",p,*p,*(*p));
like following a trail of pointers.
p is the pointer itself, printing it should print out the pointer's value which is the address of what it points to. In your case its an array of (int *)'s.
*p is a dereferencing operation. It allows access to the object that p points to. In the other answers you see notes made about *p being equivalent to p[0]. That's because p is pointing to the beginning of your structure, which is the start of the array.
**p is a dereferencing operation on the pointer object that p points to. Extending the example in the previous point, you can say that **p is equivalent to *(p[0]) which is equivalent to *(a) which is equivalent to a[0].
One tip that might help you when trying to decipher these sorts of statements is that keep in mind the precedence rules of C and insert parens between expressions in the statement to break up the statement. For the **p, inserting parens would do this: *(*p) which makes it clear that what you're doing is to follow two pointers to the final destination.

With those extra parentheses, the commas become comma operators so only the final **p is passed to printf. Since printf expects its first argument to be a pointer to a character string, and on most systems pointers
and integers have the same size, so the integer 0 is interpreted as a NULL pointer, and printf prints nothing at all. Or it crashes. That's the trouble with undefined behavior.

Your printf() arguments work like so:
p is an address (it's an array of pointers)
*p is also an address (it's equivalent to p[0], which is just a)
*(*p) is an integer (it's a[0])

My memory on C pointers is a tiny bit rusty, but let me see if I can recall.
p should be a memory location, it points to nothing else, other than p.
*p dereferences (goes to the memory location and returns the value there) p. since p itself is a pointer to pointers (*p[] can be also written as **p) when we dereference p we get the first value in the array definition, or the address of a.
**p dereferences *p. *p is the address of a. If we dereference that, we'll get the value we put in the first location of a, which is 0

Related

Can I dereference the address of an integer pointer?

I am trying to figure out all the possible ways I could fill in int pointer k considering the following givens:
int i = 40;
int *p = &i;
int *k = ___;
So far I came up with "&i" and "p". However, is it possible to fill in the blank with "*&p" or "&*p"?
My understanding of "*&p" is that it is dereferencing the address of an integer pointer. Which to me means if printed out would output the content of p, which is &i. Or is that not possible when initializing an int pointer? Or is it even possible at all anytime?
I understand "&*p" as the memory address of the integer *p points to. This one I am really unsure about also.
If anyone has any recommendations or suggestions I will greatly appreciate it! Really trying to understand pointers better.
Pointer Basics
A pointer is simply a normal variable that holds the address of something else as its value. In other words, a pointer points to the address where something else can be found. Where you normally think of a variable holding an immediate values, such as int i = 40;, a pointer (e.g. int *p = &i;) would simply hold the address where 40 is stored in memory.
If you need the value stored at the memory address p points to, you dereference p using the unary '*' operator, e.g. int j = *p; will initialize j = 40).
Since p points to the address where 40 is stored, if you change that value at that address (e.g. *p = 41;) 41 is now stored at the address where 40 was before. Since p points to the address of i and you have changed the value at that address, i now equals 41. However j resides in another memory location and its value was set before you changed the value at the address for i, the value for j remains 40.
If you want to create a second pointer (e.g. int *k;) you are just creating another variable that holds an address as its value. If you want k to reference the same address held by p as its value, you simply initialize k the same way you woul intialize any other varaible by assigning its value when it is declared, e.g. int *k = p; (which is the same as assigning k = p; at some point after initialization).
Pointer Arithmetic
Pointer arithmetic works the same way regardless of the type of object pointed to because the type of the pointer controls the pointer arithmetic, e.g. with a char * pointer, pointer+1 points to the next byte (next char), for an int * pointer (normal 4-byte integer), pointer+1 will point to the next int at an offset 4-bytes after pointer. (so a pointer, is just a pointer.... where arithmetic is automatically handled by the type)
Chaining & and * Together
The operators available to take the address of an object and dereference pointers are the unary '&' (address of) operator and the unary '*' (dereference) operator. '&' in taking the address of an object adds one level of indirection. '*' in dereferening a pointer to get the value (or thing) pointed to by the pointer removes one level of indirection. So as #KamilCuk explained in example in his comment it does not matter how many times you apply one after the other, one simply adds and the other removes a level of indirection making all but the final operator superfluous.
(note: when dealing with an array-of-pointers, the postfix [..] operator used to obtain the pointer at an index of the array also acts to derefernce the array of pointers removing one level of indirection)
Your Options
Given your declarations:
int i = 40;
int *p = &i;
int *k = ___;
and the pointer summary above, you have two options, both are equivalent. You can either initialize the pointer k with the address of i directly, e.g.
int *k = &i;
or you can initialize k by assinging the address held by p, e.g.
int *k = p;
Either way, k now holds, as its value, the memory location for i where 40 is currently stored.
I am a little bit unsure what you're trying to do but,
int* p = &i;
now, saying &*p is really just like saying p since this gives you the address.
Just that p is much clearer.
The rule is (quoting C11 standard footnote 102) that for any pointer E
&*E is equivalent to E
You can have as many &*&*&*... in front of any pointer type variable that is on the right side of =.
With the &*&*&* sequence below I denote: zero or more &* sequences. I've put a space after it so it's, like, somehow visible. So: we can assign pointer k to the address of i:
int *k = &*&*&* &i;
and assign k to the same value as p has:
int *k = &*&*&* p;
We can also take the address of pointer p, so do &p, it will have int** - ie. it will be a pointer to a pointer to int. And then we can dereference that address. So *&p. It will be always equal to p.
int *k = &*&*&* *&p;
is it possible to fill in the blank with "*&p" or "&*p"?
Yes, both are correct. The *&p first takes the address of p variables then deferences it, as I said above. The *&variable should be always equal to the value of variable. The second &*p is equal to p.
My understanding of "*&p" is that it is dereferencing the address of an integer pointer. Which to me means if printed out would output the content of p, which is &i. Or is that not possible when initializing an int pointer? Or is it even possible at all anytime?
Yes and yes. It is possible, anytime, with any type. The &* is possible with complete types only.
Side note: It's get really funny with functions. The dereference operator * is ignored in front of a function or a function pointer. This is just a rule in C. See ex. this question. You can have a infinite sequence of * and & in front of a function or a function pointer as long as there are no && sequences in it. It gets ridiculous:
void func(void);
void (*funcptr)(void) = ***&***********&*&*&*&****func;
void (*funcptr2)(void) = ***&***&***&***&***&*******&******&**funcptr;
Both funcptr and funcptr2 are assigned the same value and both point to function func.

Character Pointers in C

#include <stdio.h>
int main(void){
char *p = "Hello";
p = "Bye"; //Why is this valid C code? Why no derefencing operator?
int *z;
int x;
*z = x
z* = 2 //Works
z = 2 //Doesn't Work, Why does it work with characters?
char *str[2] = {"Hello","Good Bye"};
print("%s", str[1]); //Prints Good-Bye. WHY no derefrencing operator?
// Why is this valid C code? If I created an array with pointers
// shouldn't the element print the memory address and not the string?
return 0;
}
My Questions are outlined with the comments. In gerneal I'm having trouble understanding character arrays and pointers. Specifically why I can acess them without the derefrencing operator.
In gerneal I'm having trouble understanding character arrays and pointers.
This is very common for beginning C programmers. I had the same confusion back about 1985.
p = "Bye";
Since p is declared to be char*, p is simply a variable that contains a memory address of a char. The assignment above sets the value of p to be the address of the first char of the constant string "Bye", in other words the address of the letter "B".
z = 2
z is declared to be char*, so the only thing you can assign to it is the memory address of a char. You can't assign 2 to z, because 2 isn't the address of a char, it's a constant integer value.
print("%s", str[1]);
In this case, str is defined to be an array of two char* variables. In your print statement, you're printing the second of those, which is the address of the first character in the string "Good Bye".
When you type "Bye", you are actually creating what is called a String Literal. Its a special case, but essentially, when you do
p = "Bye";
What you are doing is assigning the address of this String literal to p(the string itself is stored by the compiler in a implementation dependant way (I think) ). Technically address to the first element of a char array, as Richard J. Ross III explains.
Since it is a special case, it does not work with other types.
By the way, you should likely get a compiler warning for lines like char *p = "Hello";. You should be required to define them as const char *p = "Hello"; since modifying them is undefined as the link explains.
As to the printing code.
print("%s", str[1]);
This doesnt need a dereferencing operation, since internally %s requires a pointer(specifically char *) to be passed, thus the dereferencing is done by printf. You can test this by passing a value when printf is expecting a pointer. You should get a runtime crash when it tries to dereference it.
p = "Bye";
Is an assignment of the address of the literal to the pointer.
The
array[n]
operator works in a similar way as a dereferrence of the pointer "array" increased by n. It is not the same, but it works that way.
Remember that "Hello", "Bye" all are char * not char.
So the line, p="Bye"; means that pointer p is pointing to a const char *i.e."Bye"
But in the next case with int *
*z=2 means that
`int` pointed by `z` is assigned a value of 2
while, z=2 means the pointer z points to the same int, pointed by 2.But, 2 is not a int pointer to point other ints.So, the compiler flags the error
You're confusing something: It does work with characters just as it works with integers et cetera.
What it doesn't work with are strings, because they are character arrays and arrays can only be stored in a variable using the address of their first element.
Later on, you've created an array of character pointers, or an array of strings. That means very simply that the first element of that array is a string, the second is also a string. When it comes to the printing part, you're using the second element of the array. So, unsurprisingly, the second string is printed.
If you look at it this way, you'll see that the syntax is consistent.

How if(some pointer) in C works?

I'm a beginner in C and I'm trying to understand the concept of pointer arithmetic:
I have a code like this :
#include<stdio.h>
void main(){
int a[10];
if(a)
printf("%d\n",*a);
}
Which prints the address of first element in array a. That's fine. But in my printf statement I'm using the * operator to print the value.
But when I look at my if statement, I wonder how without * operator, if is working on a?
I mean without * operator, how the if statement accesses the object the pointer points to?
I guess i'm clear enough about my doubt, thanks in advance.
Which prints the address of first element in array a
In your code *a is equivalent with a[0]. You're not printing any address, just some uninitialized value.
EDIT as per comment:
no my question is without * operator, how the if statement accesses
the object the pointer points to
In your code if (a) doesn't access the contents, it only tests the address of a - which will never evaluate to 0.
In C there is no type for a boolean so the body of an if-statement is executed when the condition doesn't equal 0 (zero). And it's quite sure that a doesn't point to the address 0, so the condition evaluates to true.
if (a)
basically checks if a is a null pointer.
When you declare
int a[10]
you allocate a space of memory of 10 integers, starting at the address 'a'.
When you printf *a the compiler prints the first element becuase you're telling it to print the element at the address *(a + offset) which in your case offset = 0;
To convince yourself you can try doing
int *a=null;
if (a)
{
//code here won't be executed because a points to a null reference
}

the difference between array identifier and address of array identifier

Following program would state my doubt clearly I think,so I posted the program:
#include <stdio.h>
int main() {
int a[]={1,2,3,4,5};
if(&a[0] == a)
printf("Address of first element of an array is same as the value of array identifier\n");
if(&a == a)
printf("How can a value and address of an identifier be same?!");
return 0;
}
This is the link to output: http://ideone.com/KRiK0
When it is not the subject of the sizeof or unary & operators, an array evaluates to a (non-lvalue) pointer to its first element.
So &a is the address of the array a, and a evaluates to the address of the first element in the array, a[0].
That the address of the array and the address of the first element in the array are the same is not surprising (that is, they point to the same location even though they have different types); the same is true of structs as well. Given:
struct {
int x;
int y;
} s;
Then &s and &s.x point to the same location (but have different types). If converted to void * they will compare equal. This is exactly analogous with &a and &a[0] (and consequently just a).
C++ has an implicit conversion between an array reference and a pointer. This has been asked many times before, see for example this SO question.
In C, you can get away with comparing two different types of pointers, but your compiler should give you a warning.
If I get your question right. Your int a[]={1,2,3,4,5}; I believe only stores the address of element 0 so putting this if(&a[0] == a)
is probably not required. The c string theory states that an array identifier without the bracket is the address of the first element of the characters. "a" is not defined in the program. it would probably give you a stack error. I would write it this way if(&a == a[]){printf("------"); this would only compare the address of the pointer to the address of the first element of the array.

c char arrays and pointers

#include<stdio.h>
int main(){
char a[6],*p;
a[0]='a';
a[1]='b';
a[2]='c';
a[3]='4';
a[4]='e';
a[5]='p';
a[6]='f';
a[7]='e';
printf("%s\n",a);
printf("printing address of each array element");
p=a;
printf("%u\n",&p[0]);
printf("%u\n",p+1);
printf("%u\n",a+2);
return 0;
}
The output is as follows...
anusha#anusha-laptop:~/Desktop/prep$ ./a.out
abc4epfe
printing address of each array element3216565606
3216565607
3216565608
When I declared the array as char a[6] why is it allowing me to allocate a value at a[7]? Does it not need a null character to be appended for the last element?
Also p=a => p holds the address of first element of char array a. I don’t understand how it is correct to place an '&' in front of an address (p[0]). &p[0] means address of address of first element of a which doesn't make any sense, at least to me.
Why is it printing the correct output?
You have just invoked undefined behaviour. There's little point in reasoning about writing beyond the bounds of an array. Just don't do it.
&p[0] means address of address of first element of a[] which is not sensible
No, that's perfectly sensible. Your description perfectly describes what is going on. &p[0] is the same as p which is the same as a. When you write p[0] you are dereferencing the pointer. When you then write &p[0] you are taking the address of that variable and thus return to what you started from, p.
The highest valid index of a is 5, so you're writing outside the array bounds by two, and yes, it still needs a NULL terminator. The fact that it worked was just a coincidence; writing outside array bounds is undefined behaviour. It could work, it could crash your computer, it could go buy pizza with your credit card, or something entirely different. You have no idea what it will do, so just don't do it.
when i declared the array as char a[6] why is it allowing me to allocate a value at a[7]?
because C and C++ don't care, there is no bounds check on arrays.
Does it not need a null character to be appended for the last element?
no. e.g. when you declare an array say char a[7]; you tell the compiler you want seven bytes nothing more, nothing less. however if you try to access outside the array it is your problem.
I donot understand how it is correct to mark an '&' infront of an
address(marked by p[0]). '&p[0]' means address of address of first
element of a[] which is not sensible right?How come it is printing
correct output?
if you write p[0] you are referencing the value of the array p e.g. if int p[2] = {1,2}; then p[0] is 1
if you write &p[0] you are getting the address of p[0] which is basically the same as p + 0
When I declared the array as char a[6] why is it allowing me to allocate a value at a[7]?
Because you told it to do that. You're the boss. If you tell it to jump off a cliff, it might.
Does it not need a null character to be appended for the last element?
It's not a string, it's an array of characters. It does not need a zero at the end unless you want to treat it as a string. By passing it through a %s specifier to printf, you are treating it as a string, so you need to append a zero at the end, otherwise, you're passing something that's not a string through a format specifier that requires a string.
Also p=a => p holds the address of first element of char array a. I don’t understand how it is correct to place an '&' in front of an address (p[0]). &p[0] means address of address of first element of a which doesn't make any sense, at least to me.
It works like this:
p is a pointer to the first element.
&p is the address of the pointer.
p[0] is the first element in the array the pointer points to.
&p[0] is the address of the first element in the array the pointer points to.
Why is it printing the correct output?
Sheer luck. Most likely, the implementation, being 32-bits (4 bytes) couldn't do anything useful with the two bytes after the 6-byte array. So it rounded it up to 8 bytes so that the next thing after it would start at an even 32-bit boundary. So you used two bytes the implementation wasn't using for anything anyway.
It allows you to allocate a value at a[7] because you're lucky. That's undefined behaviour. See here: http://ideone.com/ntjUn
Segmentation fault!
I hope this helps you a little with understanding the array&pointer relationship:
a[i] == *(a+i) == *(i+a) == i[a]

Resources