Can anybody explain how its printing output as "ink" - c

I am new to pointers in C. I know the basic concepts. In the below code, why is it printing the "ink" as its output?
#include<stdio.h>
main()
{
static char *s[]={"black","white","pink","violet"};
char **ptr[]={s+3,s+2,s+1,s},***p;
p=ptr;
++p;
printf("%s",**p+1);
}
Thanks

Let's trace it:
ptr = {pointer to "violet", pointer to "pink", pointer to "white", pointer to "black"}
p = ptr --> *p = pointer to "violet"
++p --> *p = pointer to "pink"
This implies that:
*p = {'p','i','n','k','\0'}
Which means:
**p = 'p'
**p + 1 = 'i'
so **p + 1 is a pointer to this string: {'i', 'n', 'k', '\0'}, which is simply "ink".

s is an array of char * (which represent strings).
ptr is an array of pointers to pointers (pointing to the values of s, which are pointers to strings)
p is set to point to ptr[0] (which is a pointer to s[3] or "violet")
p is incremented to point to ptr[1], which points to s[2] or "pink"
In the printf statement p is dereferenced twice. The first deref is a pointer to s[2], the second deref gets you the value of s[2] - "pink". The +1 shifts the pointer to the start of "pink" on by one char, so printing from here to the end of the string will give you "ink".

I'd advise that you work backwards from what you know was printed (the 'ink' in 'pink') and see where the different variables must be pointing for that to happen.
Remember that an array can be viewed as a pointer to its first element and that a string can similarly be viewed as a pointer to its first character.

static char
*s[]={"black","white","pink","violet"};
In the above statement you are initialize.
char **ptr[]={s+3,s+2,s+1,s}
In the above statement you are assign pointer s value to ptr
value. And declare a triple pointer.
p=ptr;
In the above statement you assign the double pointer address to
triple pointer.
++p;
In the above statement you increment the triple pointer value. So
that time it point to "pink".
But you are print the **p+1. That time it will print only "ink".
If you print **(p+1), that time it
will print "white". Because in the
initialization of double pointer you
initialize the "s+2". So that time it
will points to the "white".

Related

why name of string contain address of itself in c

How is it possible, name of string contains address of string - YES ok
but its (name of string) address should be different, but it is the same
NOT only that , *str gives the first character - that's ok
but *str is nothing but value at(6356737), in this code
but that itself is equal to 6356737 and not 'f'(which is nothing but str[o])
int main()
{
char str[] = "fdsgugreui";
printf("\nstr=%u,&str=%u : *str = %c\n",str,&str,*str);
int i=0;
while(str[i] != '\0'){
printf("\n&str[%d] =%u : str[%d] = %c\n ",i, &str[i], i, str[i]);
++i;
}
return 0;
}
//result...
str=6356737,&str=6356737 : *str = f
&str[0] =6356737 : str[0] = f
&str[1] =6356738 : str[1] = d
&str[2] =6356739 : str[2] = s
&str[3] =6356740 : str[3] = g
&str[4] =6356741 : str[4] = u
&str[5] =6356742 : str[5] = g
&str[6] =6356743 : str[6] = r
&str[7] =6356744 : str[7] = e
&str[8] =6356745 : str[8] = u
&str[9] =6356746 : str[9] = i
Process returned 0 (0x0) execution time : 0.150 s
Press any key to continue.
I cannot understand why!
str is the char array which decays into a pointer to the first element of the char array - which is same as &str[0].
Note that value-wise str and &str are the same but their type is different. str decays into pointer - so it becomes char* but the second one is char(*)[11] (note when you pass array name as operand of & it won't decay into pointer) which is a pointer to an array object.
The correct way to print address is printf("%p",(void*)str); and this also will be same for other pointer variables.
str[0] is the content of the array str at the position 0. That's it - it has nothing to do with having an address, It is a char. In your case str[0] is nothing but 'f'.
What is array decaying?
So in most situations, the array is converted to the pointer to the first element. This is array decaying. Notice the case here str is an array of chars - when we use str in printf it is converted to a pointer to the first element of itself which is address of str[0] and the pointer contains that value. This explains why you get the value of &str[0] when you printed str.
There are a few exceptions to array decaying:
it is the operand of the sizeof operator.
the _Alignof operator, or
the unary & operator, or
is a string literal used to initialize an array.
The fun part is &str here you see it is an operand to & address of operator - this is an exception where the decaying won't happen. So &str is a pointer to an array object. The type is char (*)[]. And yes, as you sae it will be of the same value as that of str or &str[0] but it's type is completely different.
What is char(*)[SIZE]?
It is denoting a pointer to an array of chars which has the size of SIZE. There are SIZE elements in the array.
Is char (*p)[SIZE] same as char* p[SIZE]?
Noo. It is not. First one is a pointer to an array of chars which has SIZE number of elements.
char* p[] is an array of char*-s. These are not the same. The first one is denoting a single pointer and the second is an array of pointers.
Another thing is - for pointers there are two things that matter
The value of the pointer.
The type of the pointer.
The second one dictates how the pointer arithmetic will be depending on the size of the type of object it points to. In here also you saw that &str and str has same value but not the same type. You will be surprised if you see these statement and print it.
printf(" &str+1 = %p str+1 = %p\n",(void*)(&str+1),(void*)(str+1));
Hint: The first one &str is a pointer to an array. The second is pointer to a char.

C program: pointer and pointer of string

This is the code that make me confused.
static char *s[] = {"black", "white", "pink", "violet"};
char **ptr[] = {s+3, s+2, s+1, s}, ***p;
p = ptr; // p point to the address of (s+3), so "violet"
++p; // p point to "pink"
printf("%s", **p+1); // I though it print "pink" but answer is "ink", I'm not sure about the sequence of ** and +, which executes first and how is this one begins from "i"?
After ++p, p does not point to "pink". It points to ptr[1], and ptr[1] points to s[2], and s[2] points to the first character of "pink".
*p is ptr[1], and **p is s[2]. So **p + 1 is &s[2][1], i.e. the "i" in "pink".
It is like:
char *ptr = **p; // ptr points to the 'p' in "pink"
printf("%s", ptr + 1);
static char *s[] = {"black", "white", "pink", "violet"};
The above statement defines s to be an array of characters and initializes its elements with pointers to the first element of the string literals enclosed in braces. static means the array s has internal linkage and its lifetime extends across the entire program run.
char **ptr[] = {s+3, s+2, s+1, s}, ***p;
The above statement defines ptr to be an array of objects of type char **, i.e., pointer to pointer to characters. It also defines p of type char ***, i.e., a pointer to a pointer to a pointer to a character. It initializes ptr with pointers to elements of the array s.
Therefore, ptr[0] points to s[3], ptr[1] points to s[2] and so on. The below two statements are equivalent. This is because the array ptr decays (evaluates) to a pointer to its first element.
p = ptr;
// the above is equivalent to
p = &ptr[0];
++p; // makes p point to the next element of ptr
The side effect of executing the above statement is to increment p, i.e., make it point to the next element which is ptr[1].
**p+1
Indirection operator * has higher precedence. Therefore, **p is evaluated first. Since p is pointing to ptr[1], *p evaluates to ptr[1]. Now ptr[1] is pointing to s[2], therefore **p evaluates to s[2]. s[2] is pointing to the first element of the string literal "pink". This means **p + 1 points to the next element, i.e, 2nd element which is 'i'.
printf("%s", **p + 1); // prints ink
// equivalent to
printf("%s", "pink" + 1); // prints ink
// equivalent to
printf("%s", &"pink"[1]); // prints ink
**p points to pink (i.e. **p == s[2]). Incrementing that pointer (**p) + 1 will make it point to the i in pink, so printf will print ink. Elementary. :)
The rule of thumb is that if you feel the need for declaring a triple-pointer, you are doing something wrong.
*p gives ptr[1]
**p gives value stored at s+2 i,e "pink" and it points to character p
now **p+1 gives the string ink

pointers increment in c

#include<stdio.h>
int main()
{
static char *s[]={"black","white","pink","violet"};
char **ptr[]={s+3,s+2,s+1,s},***p;
char a[]={"DEAD"};
p=ptr;
++p;
printf("%c\n",a[0]);
printf("%s\n",*s); //black
printf("%s\n",*s+1); //lack
//printf("%s\n",s+1);
printf("%s\n",s[0]);//black
printf("%s\n",s[1]);//white
printf("%s\n",s[2]);//pink
printf("%s\n",s[1]);//violet
printf("%s\n",s[1]+1);//hite
printf("%s\n",s[1]+6);//pink
printf("%s\n",**p+1); // how does this prints ink
return 0;
}
output:
D black lack black white pink white hite pink ink
please help to understand
so, p is a pointer to a pointer to a string, which basically is a pointer to a char.
p itself points to the first element of the ptr array; after p++ it points to the second, which is s+2.
s+2 points to the third element in the s array, which is "pink"
these are the two levels od dereferencing performed by **p
now, **p points to the first character of "pink", thus **p+1 points to the 'i'
now, printf takes the pointer to the i and prints everything until the next null byte, resulting in "ink" being printed to your console.
I assume you have no problem with lines I haven't directly copied
printf("%s\n",*s+1); //lack
*s+1 is the same as (*s) + 1
printf("%s\n",s[1]+6);//pink
s[1]+6 is the same as (s[1]) + 6. s[1] has type char*, so s[1]+6 points 6 characters to the right. But it's illegal to do that: s[1] only points to 6 valid characters. You just had (bad) luck that your program didn't crash.
printf("%s\n",**p+1); // how does this prints ink
approximately the same things go for **p+1 :)
You have to understand pointers.
s[0] is exactly the same as *s.
If you have s[0]+1, it points one char further than s[0].
s[1] is the same as *(s+1), but it is completely different from *s+1, which is the same as s[0]+1.
You have to draw arrows on a blackboard.
p = ptr;
++p; /* p now points to the second element of ptr "s+2" */
/* s+2 points to the third element of s "pink" */
/* **p+1 will point to the second character of "pink", thus "ink"; essentially **(s+2)+1 */

C: pointer of char & segmantation fault

In the next code:
char i,*p;
i = 65;
p = &i;
p = (char *) 66;
(*p)++;
printf("%d",p);
I got segmentation fault. I didn't understand why. I have a pointer to a char (in this case char 66=C), and then I change it value, which is also 66 - to 67. Are the values of char "protected" from this change? Is it happen also with others, except char?
I tried to understand the idea that stand behind this thing (and not only fix it). Thanks.
Here is the problem:
p = (char *) 66;
It should be:
*p = 66;
p is a pointer to a char, so you cannot assign values like 66 to it. You can derefernce p in order to assign values to where the pointer "looks".
If you want to print the value where p points to, you must use again the dereference operator (*) like this:
printf("%d", *p); // prints the value where p points to
If you want to print the pointer address you can do this:
printf("%p", p); // prints the address where p points
A character pointer doesn't store a character, it stores an address where a character can be found. So
p = (char *)66;
says that p points to address number 66, where a character can be found. Odds are that address isn't even accessible by your program, much less that it stores a character.

Differences between pointer initializations

I am speaking in Standard, K&R C.
Given:
const char a[] = {1, 2, 3};
const char *p = NULL;
Are these two statements equivalent:
*p = a;
p = a;
Each of them would be on the third line of the snippet.
1 and 2 certainly don't look the same.
What's the difference between the two then?
No.
p = a initializes the pointer to point to something else (usually it copies another pointer or you will point to a reference, ala p = &a.
*p = a initializes what p refers to. You are "dereferencing" (looking at) what p points to. If p points to NULL as in your example, you will crash (this is good! you do not want to accidentally access something and mess your program up).
In this case, p = a will point to the first of the array a[], and *p = a will attempt to change the first of the array (it won't work; you have it declared const).
Here is a small example program in C++, with almost identical syntax to C.
#include <iostream>
int main()
{
char arr[5] { 'a', 'b', 'c' }; // arr[3] and arr[4] are set to 0
char *ptr = arr; //point to 'a'
for (int i = 0; i != 5; i++)
{
*ptr = 'f'; //this changes the array
ptr++; //this changes what the pointer points to; moves it to next in array
}
for (int i = 0; i != 5; i++)
{
std::cout << *ptr << " ";
}
//outputs f f f f f
}
The * operator is what we call the dereference operator. To understand what it does, you must understand exactly what a pointer is.
When you do
char *p;
the "variable" p does not use the same amount of memory as a normal char, it uses more memory: it uses the amount of memory needed to correctly identify a memory position in your computer. So, let's say you use a 32-bit architecture, the variable p occupies 4 bytes (not the 1 byte you would expect from a char).
So, when you do
p = a;
you see clearly that you are changing the contents of the variable p, that is, you are putting another 32-bit number inside it: you are changing the address it is pointing to.
After that line executes, the value of p is the memory address of the character array a.
Now for the dereference operator. When you do
*p = 'Z';
you are telling the compiler that you want to store the value 'Z' ON THE ADDRESS pointed by p. So, the value of p remains the same after this line: it continues to point to the same address. It's the value of this address that has changed, and now contains 'Z'.
So, the final effect of
char a[] = {'a', 'b', 'c'};
char p = a;
*p = 'Z';
is the same as changing the first position of the array a to 'Z', that is:
char a[] = {'a', 'b', 'c'};
a[0] = 'Z';
NOTE: there is a difference when making a pointer point to an array: the variable that contains the array contains only the address of the first element, so a is the same as "the starting address of the array".
Usually you will see the & operator. It is an operator used to obtain the memory address of a variable. For example:
int number = 42;
int pointer = &number;
printf("%d", *pointer);
Here we have them all. The first line creates an integer variable and stores 42 inside it.
The second line creates a pointer to an integer, and stores the address of the variable number inside it.
The third line reades the value on the address pointed by the pointer.
So, the trick is to read *x as on the address pointed by x and &x as the address of x.
The first dereferences a null pointer, and tries to assign it the address of the array. This will be a compiler error, because char != char []. If it weren't, it would likely crash.
The second sets p to point to the the array.
I think you are mistaking:
char a[8];
char *p=a;
which is legal and does the same as:
char a[8];
char *p=NULL;
p=a;
with:
char a[8];
char *p=NULL;
*p=a;
which as others said would generate a compile error or a segmentation fault.
In the left side of declarations you should read *x as pointer(x) while in
statements it must be read as value_pointed_by(x). &x on the other hand
would be pointer_to(x)
Here's a trick I used when I learned C (and still use today).
Whenever you see the * in front of a variable in your code, automatically read it as "what is pointed to by".
So you should be able to easily see that setting "p" to "a" is very different from setting "what is pointed to by p" to "a".
Also, since p is supposed to be pointing at a char, setting that char p is pointing at (currently the "char" at memory location 0 assuming null is 0) to a char pointer (a) is probably going to fail at compile time if you are lucky (depending on your compiler and lint settings it may actually succeed.)
from comment:In a function declaration like f(char c), I usually try to separate out the variable name from the rest of it--so it would be f( (char) c). so c is a char*. Exactly like a variable definition.
Also & usually reads as "The address of", but that gets even more iffy. A few examples of how I read things to myself. May or may not help you.
int a[] = {1,2,3}; // I mentally parse this as (int[]) a, so a is an int array.
int *p; // p is a pointer to "integers"
int i;
p=a; // p acts exactly as a does now.
i=*p; // i is "What is pointed to by" p (1)
i=p; // i is some memory address
i=*a; // i is what is pointed to by a (1)
i=p[1]; // Don't forget that * and [] syntax are generally interchangable.
i=a+1; // Same as above (2).
p=&i; // p is the address of i (it can because it's a pointer)
// remember from hs algebra that = generally reads as "is", still works!
*p=7; // what is pointed to by p (i) is 7;
a=*i; // whoops, can't assign an array. This is the only difference between
// arrays and pointers that you will have to deal with often, so feel
// free to use which ever one you are more comfortable with.
char c='a';
char * d = &c;// d is a char pointer, and it is the address of c
char ** e ; // e is a pointer to a memory location containing
// a pointer to a char!
e=&d; // gets d's address. a pointer to a pointer gets
// the address of a pointer. Messy but gets the job done
**e=5; // what is pointed to by what is pointed to by e is 5.
*e=&'f'; // what is pointed to by e (which is a char * itself, and is still d!)
// is set to the address of the memory location holding the value 'f'.
// does not change c or e, just d!
I haven't touched c in 10 years, so some of this may be a bit wrong, but it helps me to read it out loud that way.
No, they are not equivalent
If p = NULL, then doing *p = a will give you a segmentation fault.
Because "*p" dereferences the pointer wouldnt this make "p" a "char**" ?
This would point "p" to the first array as expected.
I guess they are not the same.

Resources