Pointer to pointer gives segmentation fault? - c

Here is the code
int main
{
char s[]="prady";
char **p;
p=(char **)&s;
printf("%u %u\n",p,*p);
printf("%u %u\n",&s,s);
printf("%s\n",s);
printf("%s\n",&s);
printf("%u %u\n",s+1,&s+1);
printf("%s\n",p);
printf("%s\n",*p);
}
o/p:
3217062327 1684107888
3217062327 3217062327
prady
prady
3217062328 3217062336
prady
Segmentation fault
My doubt as follows
How both the address is same of s and &s?
If both are same then how they show different when adding 1 to it?
How I got segmentation fault in *p?

First, arrays are not pointers. Pointers are not arrays. Arrays decay into pointers.
1.How both the address is same of s and &s?
char s[]="prady";
--------------------------
s: | p | r | a | d | y | \0 |
--------------------------
The array s is a request for 6 characters to be set aside. In other words, at s there are 6 characters. 's` is a "thing", it doesn't point at anything, it just is.
char *ptr = "prady";
------ --------------------------
|*ptr| --> | p | r | a | d | y | \0 |
------ --------------------------
The pointer ptr requests a place which holds a pointer. The pointer can point at any char or any string literal (continuous chars).
Another way to think about this:
int b; //this is integer type
&b; //this is the address of the int b, right?
int c[]; //this is the array of ints
&c; //this would be the address of the array, right?
So that's pretty understandable how about this:
*c; //that's the first element in the array
What does that line of code tell you? if I deference c, then I get an int. That means just plain c is an address. Since it's the start of the array it's the address of the array, thus:
c == &c;
2. If both are same then how they show different when adding 1 to it.
From my answer to #1 I assume you see why they're not the same. So why do you get different values?
Look at the values you get:
s = 0x3217062327
s+1 = 0x3217062328 // It's 1 bigger, why? Because a char takes 1 byte, s holds chars
// so s (address of a char) + 1 (sizeof char) gives you one more than s
&a + 1 //This is adding 1 (sizeof array) which is bigger than the size of a char
3. How I got segmentation fault in *p.
I think you can get this from my previous two answers...
But:
p is a pointer to a pointer to a character
You set p to the address of the array (which remember, is the array itself)
a deference of p is a pointer to a char (another address), however you can't do that to the array.
When you typecast you tell the compiler "I know better then you so just make these two work". When you segfault... it's because you didn't really know better.

In your case s isn't a pointer. It is an array!
a small change will fix a thing:
char *s = "prady";

1.How both the address is same of s and &s.
s is an array of characters. But, arrays are converted to pointers, save in a few cases: when they are used to initialize an array (e.g: your char s[]="prady";
line), when they are the operand of the unary & operator (plenty of cases in your code), and when they are the operand of the sizeof operator.
2.If both are same then how they show different when adding 1 to it.
They are not the same.
2.How I got segmentation fault in *p.
p contains the address of "prady". *p contains "prady". Attempting to use "prady" as if it were the address of a string causes a segfault.

Related

Confusion about the way C handles strings

Why wouldn't
char *name = "asd";
printf("%p\n%p", (void *)&name, (void *)&name[0]);
give the same output as
char name[] = "asd";
printf("%p\n%p", (void *)&name, (void *)&name[0]);
I've read that C takes strings as a pointer to their first char, till it reaches the '\0' but the code above doesn't like it, so it is confusing for a C beginner.
First, let's give your two variables different names and contents, so we can clearly tell them apart.
char *namep = "asd";
char namea[] = "zxc";
These result in data structures which might look like this:
+-------+
namep: | * |
+---|---+
|
/
|
V
+---+---+---+----+
| a | s | d | \0 |
+---+---+---+----+
+---+---+---+----+
namea: | z | x | c | \0 |
+---+---+---+----+
Now let's look at your two printf calls:
printf("%p\n%p", (void *)&namep, (void *)&namep[0]);
Now, &namep gives you the address of the namep pointer.
But &namep[0] gives you the address of the first character in the pointed-to string (a). If you had printed
printf("%p\n", (void *)namep);
you would have seen the same thing.
printf("%p\n%p", (void *)&namea, (void *)&namea[0]);
Here, &namea gives you the address of the array.
And &namea[0] gives you the address of its first character (z) — which is the same place.
And in fact, due to the special handling (the "decay" of arrays into pointers), if you had said
printf("%p\n", (void *)namea);
you would also have seen the same thing.
You asked:
I've read that C takes strings as a pointer to their first char, till it reaches the '\0'.
That's correct.
Suppose you wrote the code
char *p;
for(p = namep; *p != '\0'; p++)
putchar(*p);
This would print your namep string, asd. There's no mystery here. namep was already a pointer, pointing at the first character of the string, so this scrap of code takes its own pointer p, which starts pointing where namep points, and prints the pointed-to characters until it gets to the terminating \0.
What's perhaps more surprising is that you can do exactly the same thing with namea:
char *p;
for(p = namea; *p != '\0'; p++)
putchar(*p);
This works, too, printing zxc, and if you don't believe me, I encourage you to type it into your C compiler and try it.
Now, you may be asking, if p is a pointer and namea is an array, how can the loop initialization p = namea work? And this, again, is due to the "decay" of arrays to pointers. Again, when you try to use namea's value like this, what you get — the value that gets assigned to p — is automatically a pointer to namea's first element. And of course that's just what you want. p starts there, and prints characters 'til it finds a \0, thus printing zxc.

Why this simple program in C crashes (array VS pointer)

I have two files:
In file 1.c I have the following array:
char p[] = "abcdefg";
In file 0.c I have the following code:
#include <stdio.h>
extern char *p; /* declared as 'char p[] = "abcdefg";' in 1.c file */
int main()
{
printf("%c\n", p[3]); /* crash */
return 0;
}
And this is the command line:
gcc -Wall -Wextra 0.c 1.c
I know that extern char *p should've been: extern char p[];, but I just want an explanation of why it doesn't work in this particular case. While it works here:
int main()
{
char a[] = "abcdefg";
char *p = a;
printf("%c\n", p[3]); /* d */
return 0;
}
Your two examples are not comparable.
In your second example, you have
char a[] = "abcdefg";
char *p = a;
So a is an array, and p is a pointer. Drawing that in pictures, it looks like
+---+---+---+---+---+---+---+---+
a: | a | b | c | d | e | f | g | \0|
+---+---+---+---+---+---+---+---+
^
|
+----|----+
p: | * |
+---------+
And this is all fine; no problems with that code.
But in your first example, in file 1.c you define an array named p:
+---+---+---+---+---+---+---+---+
p: | a | b | c | d | e | f | g | \0|
+---+---+---+---+---+---+---+---+
You can name an array "p" if you want (the compiler certainly doesn't care), but then, over in file 0.c, you change your mind and declare that p is a pointer. You also declare (with the "extern" keyword) that p is defined somewhere else. So the compiler takes your word for it, and emits code that goes to location p and expects to find a pointer there -- or, in pictures, it expects to find a box, containing an arrow, that points somewhere else. But what it actually finds there is your string "abcdefg", only it doesn't realize it. It will probably end up trying to interpret the bytes 0x61 0x62 0x63 0x64 (that is, the bytes making up the first part of the string "abcdefg") as a pointer. Obviously that doesn't work.
You can see this clearly if you change the printf call in 0.c to
printf("%p\n", p);
This prints the value of the pointer p as a pointer. (Well, of course, p isn't really a pointer, but you lied to the compiler and told it that it was, so what you'll see is the result when the compiler treats it as a pointer, which is what we're trying to understand here.) On my system this prints
0x67666564636261
That's all 8 bytes of the string "abcdefg\0", in reverse order. (From this we can infer that I'm on a machine which (a) uses 64-bit pointers and (b) is little-endian.) So if I tried to print
printf("%c\n", p[3]);
it would try to fetch a character from location 0x67666564636264 (that is, 0x67666564636261 + 3) and print it. Now, my machine has a fair amount of memory, but it doesn't have that much, so location 0x67666564636264 doesn't exist, and therefore the program crashes when it tries to fetch from there.
Two more things.
If arrays are not the same as pointers, how did you get away with saying
char *p = a;
in your second example, the one I said was "all fine; no problems"?
How can you assign an array on the right-hand side to a pointer on the left?
The answer is the famous (infamous?) "equivalence between arrays and pointers in C": what actually happens is just as if you had said
char *p = &a[0];
Whenever you use an array in an expression, what you get is actually a pointer to the array's first element, just as I showed in the first picture in this answer.
And when you asked, "why it doesn't work, while it works here?", there were two other ways you could have asked it.
Suppose we have the two functions
void print_char_pointer(char *p)
{
printf("%s\n", p);
}
void print_char_array(char a[])
{
printf("%s\n", a);
}
And then suppose we go back to your second example, with
char a[] = "abcdefg";
char *p = a;
and suppose that we call
print_char_pointer(a);
or
print_char_array(p);
If you try it, you'll find that there are no problems with either of them.
But how can this be? How can we pass an array to a
function that expects a pointer, when we call print_char_pointer(a)?
And how can we pass a pointer to a
function that expects an array, when we call print_char_array(p)?
Well, remember, whenever we mention an array in an expression,
what we get is a pointer to the array's first element. So when
we call
print_char_pointer(a);
what we get is just as if we had written
print_char_pointer(&a[0]);
What actually gets passed to the function is a pointer, which is
what the function expects, so we're fine.
But what about the other case, where we pass a pointer to a function that's declared as if it accepts an array? Well, there's actually another tenet to the "equivalence between arrays and pointers in C".
When we wrote
void print_char_array(char a[])
the compile treated it just as if we had written
void print_char_array(char *a)
Why would the compiler do such a thing? Why, because it knows
that no array will ever be passed to a function, so it knows that no
function will actually ever receive an array, so it knows that the
function will receive a pointer instead. So that's the way the
compiler treats it.
(And, to be very clear, when we talk about the "equivalence
between arrays and pointers in C", we are not saying that
pointers and arrays are equivalent, just that there is this
special equivalence relationship between them. I've mentioned
two of the tenets of that equivalence already. Here are all
three of them, for reference: (1) Whenever you
mention the name of an array in an expression, what you
automatically get is a pointer to the array's first element.
(2) Whenever you declare a function that seems to accept an
array, what it actually accepts is a pointer. (3) Whenever you
use the "array" subscripting operator, [], on a pointer, as in
p[i], what you actually get is just as if you had written *(p + i). And, in fact, if you think about it carefully, due to
tenet (1), even when you use the array subscripting operator on
something that looks like an array, you're actually using it on a
pointer. But that's a pretty strange notion, which you don't
have to worry about if you don't want to, because it just works.)
Because arrays are not pointers. You tell the program "elsewhere I have a char pointer", but you actually don't have one - you have an array.
An array will decay into a pointer when used in an expression, but that doesn't mean that an array is a pointer. For more info see Is an array name a pointer?.
In your second example you have both an array and a pointer, two separate variables, so it is a different case.
Let me explain it in reverse:
In the second case, you have an array and then a pointer which points to that array.
Accessing via the pointer involves an indirect memory address ("print the 3rd byte from where this pointer points to" vs. "print the 3rd byte of this array").
In the first case, you have an array somewhere else, but tell the compiler you had a pointer at that place. So it tries to read that pointer and read the data from where it points to. But there is no pointer – there is the data immediately, so the pointer points to "anywhere and nowhere" (at least, quite likely). This constitutes undefined behaviour (often abbreviated as UB).

Why p and *p giving the same address when p points to an array?

I was writing this program -
#include<stdio.h>
void main()
{
int arr[20];
arr[0]=22;
arr[1]=23;
int (*p)[20]=&arr;
printf("address in p :%u:\n",p);
printf("address in *p:%u:\n",*p);
}
The Output of this code is same for p and *p ! So far as I know *p is holding the base address of arr which is nothing but arr[0]!!!
So *p should have give the output 22 ! But it's showing the same memory address like p is showing. Please tell me why this is happened? What is the reason behind it.
Codepad Site Link : http://codepad.org/LK7qXaqt
p is a pointer to an array of 20 integers. Address of first byte of array is said to be the address of the array. Dereferencing it will give the entire array itself. Therefore *p represents the array arr, so you can think of *p as an array name.
As array names are converted to pointers to its first element when passed to a function, *p is decayed to pointer to first element of arr. Therefore
printf("address in *p: %p:\n", (void*)*p);
will print the address of first element of array arr while
printf("address in p: %p:\n", (void*)p);
will print the address of the entire array (i.e first byte of the array). Since value of first byte and first element is same, that's why both are printing the same address.
For detailed explanation: What exactly is the array name in c?
Because p and *p points to same memory location only there types are different
+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+
arr [ ]
p [ ]
(*p)[ ]
If you print p+1 and *p + 1 you should see the difference
int (*p)[20] declare p as pointer to array of size 20 of type int so at the same time *p is the pointer to the first element of the array.
Address of first element and of whole array would be same.
Yes it is possible to apply the address operator to an array, although it seems redundant. The result p is a pointer to array. Such a thing is under normal circumstances rarely encountered. As #Mohit pointed out correctly, the object it points to is the whole array, which implies that sizeof(*p) should be the size of the array (not of its first element).
*p logically is the array then; as usual it decays to a pointer to its first element (which is an int) when passed as an argument, e.g. to printf. Since it's the first element its location in memory is the location of (the beginning of) the whole array.

Strange behavior of 'char' pointers

When I declare and run the following it gives me a segmentation fault.
main()
{
char *p = "boa";
*(p+1) = 'y';
printf("%s",p);
}
I suspect char *p is a constant, etc.
But the following works fine.
main()
{
int i = 300;
char *p = (char*)&i;
*(p+1) = 'y';
printf("%s",p);
}
What is the reason behind this? Doesn't the above rule apply to this as well?
That depends on your definition of "works fine". But the reason the assignment doesn't segmentation fault is because p was made to point to the address of the i variable, which is clearly not a constant. i was assigned a constant value, but i itself is not a constant.
For i = 300 (assuming little endian x86):
+--+--+--+--+
i:|2c|01|00|00|
+--+--+--+--+
.
/|\
|
p:&i
After *(p+1) = 'y'
+--+--+--+--+
i:|2c|79|00|00|
+--+--+--+--+
.
/|\
|
p:&i
So, the print statement just happens to print ,y for you, but only because you relied on the platform's byte ordering (and that 2c was a printable ASCII character). Things could have been different on a big endian machine, and/or if it was non-ASCII.
Oh, boy...
The first one seg-faults due to the string being const (you've got that right). The second one, however, is a fascinating abuse of the pointer semantics! ;-)
Here's what you are doing in the second example:
Have a random int number with a value (in your case - 300)
Get an address of that int - basically an address to a location that holds a (32-bit?) int of 300 and cast it to a char*, where each element points to an 8-bit value
Get the address of the "first" 8-bit value, increment by one (increment by 8 bits(!)) and change the value of those 8 bits to a numeric ASCII code of 'y'
Print the "resulting string"
The difference is this:
char *p="boa";
p is a pointer. You are making p point at a string literal "boa" which cannot be modified and when you try to modify it a segfault occurs.
int i=300;
char *p=(char*)&i;
i is a variable of type int, you only use the constant 300 to initialize i and do a bitwise copy of the value of 300 into the location of i, but you are never pointing at the constant itself, just using it as an initializer. This is the difference, p in your first example points at a constant string literal, whereas in your second example it points at a variable of type int. Hence modifying the location of i later on with the pointer p is fine because you are modifying a non constant object i.

Is it possible to convert char[] to char* in C?

I'm doing an assignment where we have to read a series of strings from a file into an array. I have to call a cipher algorithm on the array (cipher transposes 2D arrays). So, at first I put all the information from the file into a 2D array, but I had a lot of trouble with conflicting types in the rest of my code (specifically trying to set char[] to char*). So, I decided to switch to an array of pointers, which made everything a lot easier in most of my code.
But now I need to convert char* to char[] and back again, but I can't figure it out. I haven't been able to find anything on google. I'm starting to wonder if it's even possible.
It sounds like you're confused between pointers and arrays. Pointers and arrays (in this case char * and char []) are not the same thing.
An array char a[SIZE] says that the value at the location of a is an array of length SIZE
A pointer char *a; says that the value at the location of a is a pointer to a char. This can be combined with pointer arithmetic to behave like an array (eg, a[10] is 10 entries past wherever a points)
In memory, it looks like this (example taken from the FAQ):
char a[] = "hello"; // array
+---+---+---+---+---+---+
a: | h | e | l | l | o |\0 |
+---+---+---+---+---+---+
char *p = "world"; // pointer
+-----+ +---+---+---+---+---+---+
p: | *======> | w | o | r | l | d |\0 |
+-----+ +---+---+---+---+---+---+
It's easy to be confused about the difference between pointers and arrays, because in many cases, an array reference "decays" to a pointer to it's first element. This means that in many cases (such as when passed to a function call) arrays become pointers. If you'd like to know more, this section of the C FAQ describes the differences in detail.
One major practical difference is that the compiler knows how long an array is. Using the examples above:
char a[] = "hello";
char *p = "world";
sizeof(a); // 6 - one byte for each character in the string,
// one for the '\0' terminator
sizeof(p); // whatever the size of the pointer is
// probably 4 or 8 on most machines (depending on whether it's a
// 32 or 64 bit machine)
Without seeing your code, it's hard to recommend the best course of action, but I suspect changing to use pointers everywhere will solve the problems you're currently having. Take note that now:
You will need to initialise memory wherever the arrays used to be. Eg, char a[10]; will become char *a = malloc(10 * sizeof(char));, followed by a check that a != NULL. Note that you don't actually need to say sizeof(char) in this case, because sizeof(char) is defined to be 1. I left it in for completeness.
Anywhere you previously had sizeof(a) for array length will need to be replaced by the length of the memory you allocated (if you're using strings, you could use strlen(), which counts up to the '\0').
You will need a make a corresponding call to free() for each call to malloc(). This tells the computer you are done using the memory you asked for with malloc(). If your pointer is a, just write free(a); at a point in the code where you know you no longer need whatever a points to.
As another answer pointed out, if you want to get the address of the start of an array, you can use:
char* p = &a[0]
You can read this as "char pointer p becomes the address of element [0] of a".
If you have
char[] c
then you can do
char* d = &c[0]
and access element c[1] by doing *(d+1), etc.
You don't need to declare them as arrays if you want to use use them as pointers. You can simply reference pointers as if they were multi-dimensional arrays. Just create it as a pointer to a pointer and use malloc:
int i;
int M=30, N=25;
int ** buf;
buf = (int**) malloc(M * sizeof(int*));
for(i=0;i<M;i++)
buf[i] = (int*) malloc(N * sizeof(int));
and then you can reference buf[3][5] or whatever.
None of the above worked for me except strtok
#include <string.h>
Then use strtok
char some[] = "some string";
char *p = strtok(some, "");
strtok is used to split strings. But you can see that I split it on nothing ""
Now you have a pointer.
Well, I'm not sure to understand your question...
In C, Char[] and Char* are the same thing.
Edit : thanks for this interesting link.

Resources