why name of string contain address of itself in c - 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.

Related

If char *ptr[10]={"ram","try"} then what is the difference between ptr ,*ptr , *ptr[0] , ptr[0] if all given four types used in printf function

#include <stdio.h>
//Compiler version gcc 6.3.0
int main()
{
char *ptr[10]={"ram","try"};
printf("%s \n",ptr); // prints neither string nor character (may be address)(why ?)
printf("%s \n",*ptr); // prints string (why ?)
printf("%c \n",*ptr[0]); // prints character i.e. r ( why ?)
printf("%s \n",ptr[0]); // prints string (understandable)
return 0;
}
Why ptr doesn't print ram ? and why *ptr[0] doesn't print string ?
char *ptr[10]={"ram","try"};
ptr is an array of 10 pointers: ptr[0], ... to ... ptr[9]. Each element of the array is a pointer.
ptr[0] is a pointer to the string literal "ram"; ptr[1] is a pointer to the string literal "try". All the 8 other elements are null pointers (NULL).
*ptr[k] is the first character in (the string) ptr[k] if it's not NULL
printf("%s \n",ptr); prints neither string nor character (may be address)(why ?)
The "%s" specifier expects a value of type char*, you're passing the whole array of 10 pointers (type char *[10]) which is not compatible so you invoke Undefined Behaviour.
printf("%s \n",*ptr); prints string (why ?)
*ptr is a synonym of ptr[0]. It's one of the array elements and has type char*. It's not NULL, so it works as expected.
printf("%c \n",*ptr[0]); prints character i.e. r ( why ?)
*ptr[0] is the same as ptr[0][0] (or (ptr[0])[0]), ie ... the 1st character of the first pointer (the 1st string). It matches the specifier "%c" so it works as expected.
printf("%s \n",ptr[0]); prints string (understandable)
See *ptr above; they're the same.
Given the declaration
char *ptr[10] = {"ram", "try"};
the following are all true:
Expression Type "Decays" to Value
---------- ---- ----------- -----
ptr char *[10] char ** Address of first element (equivalent to &ptr[0]);
not the correct type for the "%s" conversion
specifier in printf
*ptr char * n/a Value of first element;
exactly equivalent to ptr[0]; correct type
for "%s" conversion specifier
ptr[0] char * n/a Same as above
ptr[i] char * n/a Value of the i'th element
*ptr[i] char n/a Value of the first character
of the i'th element
Graphically:
char * char
+---+ +---+---+---+---+
ptr: | | ptr[0] ----------> |'t'|'r'|'y'| 0 |
+---+ +---+---+---+---+
| | ptr[1] --------+
+---+ | +---+---+---+---+
| | ptr[2] ---||| +-> |'r'|'a'|'m'| 0 |
+---+ +---+---+---+---+
| | ptr[3] ---|||
+---+
...
where ||| represents NULL.
printf("%s \n",ptr); // prints neither string nor character (may be address)(why ?)
ptr is not a string. It is an array of strings.
printf("%s \n",ptr[0]); // prints string (understandable)
Right. ptr is an array of strings, so ptr[0] is one of those strings.
printf("%s \n",*ptr); // prints string (why ?)
Because ptr is an array of strings, and *ptr is identical to ptr[0].
printf("%c \n",*ptr[0]); // prints character i.e. r ( why ?)
ptr is an array of strings, so ptr[0] is one of those strings, and *ptr[0] is one of the characters in one of those strings.
It might be interesting to note that
printf("%c\n", ptr[0][0]);
would give exactly the same result -- that is, print the first character of the first string, just like *ptr[0].
What we're dancing around here, and what you may not have been taught properly yet, is what's sometimes called the correspondence between arrays and pointers in C. Array subscripting in C is defined in terms of pointer arithmetic. For any array a or pointer p, a[i] is by definition identical to *(a + i), and p[i] is by definition identical to *(p + i).
Another interesting fact: whenever you use string literals in C Code, consider adding the const keyword. Because if you try to modify one of these strings, this will cause undefined behaviour (most likely a segmentation fault, which in turn means that your program will crash).
This will most likely crash:
char *foo = "bar";
foo[1] = 'x'; // Undefined behavior but compiles fine
This will prevent one from editing the content of the array:
const char *foo = "bar";
foo[1] = 'x'; // Won't compile

what exactly happens when I do this assignment

Consider this snippet
char a[]="";
Will a NULL-pointer be assigned to the a character pointer *a?
If not how do I check that the no string has been assigned to a?
Will a NULL pointer be assigned to the a character pointer *a?
There is no character pointer here, but an array a of char.
a will be defined as an array of char and initialised to hold an empty-string, that is a c-string with just carrying the 0-terminator, which is one char.
how do I check that the no string has been assigned to a?
So a will have exactly one element. This element compares equal to '\0', which in turn compares equal to 0.
To test this do
#include <stdio.h> /* for puts() */
#include <string.h> /* for strlen() */
int main(void)
{
char a[] = ""; /* The same as: char a[1] = ""; */
/* Possibility 1: */
if (0 == a[0]) /* alternatively use '\0' == a[0] */
{
puts("a is an empty string.");
}
/* Possibility 2: */
if (0 == strlen(a))
{
puts("a has length zero.");
}
}
a will contain 1 element:
a[0] == '\0'
Note: a is not a pointer.
First of all, a is not a character pointer, it is an array of char. There are some cases where the latter is converted to the former, but they are inherently not the same type.
That said, in this initialization, array a will be initialized with an empty string.
Empty string means, the first element will be the terminating null character, so the easiest way to check if an array contains an empty string is to compare the first element with null, like
if (a[0] == '\0') { /*do the action*/ }
==> Will a NULL-pointer be assigned to the a character pointer *a?
Arrays are not pointers.
For better understanding, lets refer an example from C Standard#6.7.9p32 [emphasis mine]
EXAMPLE 8 The declaration
char s[] = "abc", t[3] = "abc";
defines ''plain'' char array objects s and t whose elements are initialized with character string literals. This declaration is identical to
char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };
The contents of the arrays are modifiable. On the other hand, the declaration
char *p = "abc";
defines p with type ''pointer to char'' and initializes it to point to an object with type ''array of char'' with length 4 whose elements are initialized with a character string literal. If an attempt is made to use p to modify the contents of the array, the behavior is undefined.
So, this statement
char a[]="";
defines char array object a whose elements are initialized with character string literal "". Note that "" is a string literal containing a single character '\0'.
The above statement is equivalent to
char a[] = {'\0'};
If we omit the dimension, compiler computes it for us based on the size of the initializer (here it will be 1 because initializer is only having one character '\0'). So the statement is same as
char a[1] = {'\0'};

Character Pointer in C

Experts I've some doubts in this programme.
#include<stdio.h>
void main() {
char str1[] = "Hello";
char * p = "Hello", * s, * q;
p = "Bye";
printf("%s", p);
s = p;
printf("%s", s);
q = str1;
printf("\n%s", q);
}
Here p,s and q are character pointers. As we know pointers store the address of a variable and suppose if we used p=str1 then it should store the base address of array str1. Then here how p is acting like an array itself which is storing a string? I've not really understood what's character pointer. Is it not really a pointer? Because we are not using & and neither are we getting the address as an output. Please help. Thank you.
You are very much correct here:
As we know pointers store the address of a variable and suppose if we used p=str1 then it should store the base address of array str1.
Your first question:
Then here how p is acting like an array itself which is storing a string?
You can say p is acting like an array but in reality, it is just a pointer which is pointing to the base address of string str1 which is a null-terminated string.
Your second question:
I've not really understood what's character pointer. Is it not really a pointer?
A character pointer is again a pointer like the pointers to other types in C.
But there is catch here. when you do:
char a = 'A';
char *ptr = &a; // ptr points to character 'A'
Here ptr is pointer to a character.
But when you do:
char *str = "Hello";
char *ptr = str; // ptr points to first character of string str
Here ptr is pointer to a string
A point to note here is - pointer to a character is different from the pointer to a string.
In C, strings are defined as an array of characters. The difference between a character array and a string is the string is terminated with a special character ‘\0’.
So,
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
char str[] = "Hello";
Both are same but there is a difference in the way they have been initialized.
Wherever in the program, we use str, this will give the base address of string "Hello". Similarly, string literals are also an array of characters with an exception that they can not be changed because the compiler may put them read-only data section.
So, if we have char *ptr = str then
ptr[0] == str[0]
ptr[1] == str[1]
.....
..... and so on
Because,
ptr[0] is *(ptr + 0) which is character at 0th location of string str and can also be written as *ptr and
ptr[1] is *(ptr + 1) which is a character at the 1st location of string str.
When we increment a pointer, it gets incremented in steps of the object size that the pointer points to. Here, ptr is pointer to char so, ptr+1 will give address of next character and *(ptr + 1) give the character at that location. That's why to the user it looks like its acting like an array.
Your third question:
Because we are not using & and neither are we getting the address as an output.
If I am getting it correctly you want to print the base address of the string, the pointer is pointing to.
In order to get the base address of string a pointer is pointing to you need to use %p. Like this:
#include<stdio.h>
int main() {
char str1[] = "Hello";
char * ptr = str1;
printf ("%s\n", str1);
printf ("%s\n", ptr);
printf ("%p\n", ptr);
printf ("%p\n", str1);
printf ("%p\n", &str1[0]);
return 0;
}
Output on my system:
Hello
Hello
0x7fff5e997b46
0x7fff5e997b46
0x7fff5e997b46
Here you can see - ptr, str and &str[0] giving same address.

Error in string initialisation

Here I was trying out the following thing in my code and got the following error---"prog.c:10:8: error: incompatible types when assigning to type ‘char[100]’ from type ‘char *’". Please help and tell me how can I modify my initialisation which is char str[100] to get the right answer
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[100];
str = "a";
str = str + 1;
str = "b";
str = str + 1;
str = "c";
str = str + 1;
printf("%s", str - 2);
return 0;
}
You have declared an array
char str[100];
By specifying the name of the array you will get the base address of the array which is same as the address of first element.
str="a";
In the above statement, you are trying to assign "a"s (note "a" is string here) address to array base.
The compiler will not allow you to do this. Cos, if you do so, you will lose all the 100 elements.
If you want to assign the first element with the value 'a', then do
str[0] = 'a';
Note that I have used single quote. Remember "Single quote for single char".
You have to use string commands like strcpy/strncpy.
Or you can allocate memory to accomodate the string and use only char pointers, no char array.
while arrays and pointers are closely related in C, they are not entirely the same.
char str[100];
gives you a "const pointer"-like handle to a pre-allocated array of 100 chars. this array will live at a fixed position in memory, so you cannot let str point to some other place.
str="a";
will assign the position of a string "a" to the pointer "str". (which is illegal!).
what you can do, is to assign the values within your array.
char str[100] = {0};
str[0]='a';
str[1]='b';
str[2]='c';
printf("%s", str);
treat str as an array and not as a pointer (str points to a memory address allocated for 100 chars and str[i] accesses the relative memory address of str + i)
char str[100];
str[0]='a';
str[1]='b';
str[2]='c';
str[3]='\0';
printf("%s",str);
if want initialisation a str[100],use this:
char str[100] = "abc";
it only work when we define the str[100] and initialisation str[100] at the same time!
Or you code can work in this way:
char str[100];
str[0] = 'a';
str[1] = 'b';
str[2] = 'c';
str[3] = '\0';
Or :
char str[100];
*str = 'a';
++str;
*str = 'b';
++str;
*str = 'c';
++str;
*str = '\0';
In general when you create an array of characters like this.
char string[100]; //allocate contigious location for 100 characters at compile time
Here string will point to the base address of the contigious location. Assuming memory address starts from 4000 then it would be like
--------------------------------------
|4000|4001|4002|4003|...........|4099|
--------------------------------------
Variable string will point to 4000. To store a value at 4000 you can do *(4000).
Here you can do like
*string='a'; //4000 holds 'a'
*(string+1)='b'; //4001 holds 'b'
*(string+2)='c'; //4002 holds 'c'
Note: Array can be accessed by any of the three forms in c.
string[0] => 0[string] => *(string+0) => points to first element in string array
where
string[0] => *(4000+0(sizeof(char))) => *(4000)
0[string] => *((0*sizeof(char))+4000) => *(4000)
*string => *(4000)
In case of integer array, assuming int takes 4bytes of memory
int count[100]; //allocate contigious location for 100 integers at compile time
Here count will point to the base address of the contigious location. Assuming memory address starts from 4000 then it would be like
--------------------------------------
|4000|4004|4008|4012|...........|4396|
--------------------------------------
variable count will point to 4000. To store a value at 4000 you can do *(4000).
Here you can do like
*count=0; //4000 holds 0
*(count+1)=1; //4004 holds 1
*(count+2)=2; //4008 holds 2
So coming to your code, your objective can be achieved like this.
#include<stdio.h>
#include<stdlib.h>
int main()
{
char str[100];
*str='a';
*(str+1)='b';
*(str+2)='c';
printf("%s",str);
return 0;
}
Output: abc
You persist in using the wrong term, which leads me to believe that is why you couldn't find an answer.
/* 1 */
char str[100] = "a"; //OK
/* 2 */
str = "b"; // error: str is an array
Initialization is what happens when you assign a value to a variable while declaring the variable. This is source code excerpt 1 above.
Assignment is what happens after the variable is declared. You can't assign to a struct or array type. You must address each individual item in the struct/array when assigning values. In code excerpt 2 above, the variable str is assigned the value "b", except that str is an array, so the compiler says there is an error because you can't assign to an array.
Summary:
You can initialize an array, but you cannot assign to it. The difference is in whether the variable was given an explicit value when it was declared. If it was, the variable was initialized. Otherwise, you're trying to assign to an array, which can't be done.
Many, even I when learning c, was confused like you.
Actually you must be clear on this
Difference between `char []` and `char *`
=>char [] is a constant pointer which refers to the same address every time. But its value is not constant
=>char * is a non-constant pointer which can be changed to refer to any string. Its value is also not constant, but if it is assigned the address of a const char * then its value will be const.
Coming to your question
Use methods instring.h
#include<stdio.h>
#include<stdlib.h>
int main()
{
char string[100];
char *str;
*str = 'a';
str = str + 1;
*str = 'b';
str = str + 1;
*str = 'c';
str = str + 1;
printf("%s", str - 2);
return 0;
}

Can anybody explain how its printing output as "ink"

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

Resources