I'm trying to print a pointer of char type in c , i'm able to see the values and it's memory address as below
char *ptr = "I am a string";
printf("\n value [%s]\n",ptr);
printf("\n address [%d]\n",&ptr);
But when i print directly the pointer as below, it's showing error as Segmentation fault
char *ptr = "I am a string";
printf("\n value [%s]\n",*ptr);
Please tell me what's going wrong here
Note: if i change the format in printf to [%d] or [%i] it's printing.
*ptr is a char, not a char pointer, and %s expects a char pointer (to a C-string). When treating the char as a pointer, printf tries to access an invalid memory address, and you get a segmentation fault.
The %s format specifier expects a pointer to a 0-terminated char array. If the corresponding argument to printf is *ptr, a char, that is a) undefined behaviour and b) probably leads to the value of the character (promoted to an int) and possibly some arbitrary adjacent bytes, being interpreted as a pointer. Following that presumed pointer is likely to access memory not allocated to your program.
When you pass in the format "%s" into printf, the function expects a pointer to an array of chars.
Related
This question already has answers here:
Char pointers and the printf function
(6 answers)
Closed 1 year ago.
For example, the following code returns an error and a warning when compiled and an int when changed to %d
Warning:
format %s expects argument of type char *, but argument 2 has type int
void stringd() {
char *s = "Hello";
printf("derefernced s is %s", *s);
}
*s is an expression of type char since it's the dereference operator applied to a pointer-to-char1. As a result, it gets promoted to an int when passed to printf; in order to print a null-terminated string, you need to pass the pointer to the first character (i.e. just s).
1 even though s is not a const pointer, you should not try to modify the characters it points to as they may be placed in read-only memory where string literals are stored on some architectures/environments; see this discussion for more details.
The variable s is a pointer to the first out of a series of characters which are consecutive in memory (colloquially referred to as a "string", though it's not quite the same). It's a pointer to a character, thus char *.
Dereferencing s (by doing *s) gives you the first of those characters, h, whose type is now just char. One layer of indirection was stripped away.
Thus, the issue is that you're trying to pass a character (char), where a string (char *) was expected. char * was expected because you used the %s type character in your format string to printf. Instead, you should use %c, which expects single, simple char.
The mistake here is actually quite grave. If you were allowed to pass this 'h' where a char * was expected, you would end up with the ASCII code of 'h' (0x68) being passed where a pointer was expected. printf would be none-the-wiser, and would try to dereference that value, treating 0x68 like a pointer to the beginning of a string. Of course, that's probably not a valid memory location in your program, so that should seg-fault pretty reliability, if it were allowed to happen.
I've seen some similar questions asked on here, but haven't been able to find a concise answer.
In learning pointers, I've come to understand that
in a case of
int test=1; int* p = &test;
printing "p" with printf("%p", p); will give the address of test, while printing *p with printf("%d", *p); will give the actual value of test, which is what ptr p points to.
Now, for doing this with a char, doing
char word[] = "test"; char* ptr = &word[0];
then printing ptr with printf("%s", ptr); gives the output "test", but I expected it to give the address of word[0].
I have figured out that if I do printf("%p", ptr); it does print the address.
So my question is, does this pointer contain both the address and the value of the array test[]? Or does printf just grab what it needs based off of which of %s or %p you use, and in that case, why couldn't you just do printf("%d",test); in my earlier example and get the value of test rather than the address? Is the fact that I'm using %s automatically outputting the entire array since it starts at that address?
%s tells printf to take the pointer it is given and print the first character that is there, then the character after that, then the character after that, and so on until printf finds a null character (a character that has value zero).
So, this not about a pointer pointing to the “entire array.” The pointer just points to one thing. It is about the command given to printf. %p says “print the value of the pointer.” %s says “print the characters at the location pointed to.”
… why couldn't you just do printf("%d",test); in my earlier example and get the value of test rather than the address?
%d is a command to printf to print the value of the int it is passed. You should not pass it a pointer for this because printf is expecting an int. That is just what the command is for.
I declare a pointer like this:
char *ptr = "hello";
and when I do this
printf("%p\n", *&*&ptr);
the result is address of that pointer, but when I do this
printf("%s\n", *&*&ptr);
the result is hello.
Can someone explain why?
*&*&ptr is a weird way of writing ptr (since * cancels out &).
%p expects a pointer, and prints the value of the pointer (i.e. the address to which it points). The value of ptr is therefore a valid input, and you are seeing the expected result.
%s expects a pointer to a NUL-terminated sequence of char values, and prints those char values (but not the NUL). The value of ptr is therefore a valid input, and you are seeing the expected result.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *myptr = calloc(500,1);
char *myptr2 = myptr;
*myptr++ = 'A';
*myptr++ = 'B';
*myptr = '\0';
/* This should dereference the beginning of the memory and print until myptr[2] which is '\0' */
printf("Myptr2 points to: %s\n", *myptr2);
free(myptr);
return(EXIT_SUCCESS);
}
Why is line 13 (the printf line) creating a SIGSEV? It should be pointing to the beginning of the memory and then printf should print until it hits the '\0'.
can you tell conceptually what the problem is? If you dereference a pointer to the memory, what does this cause?
When you have a %s slot in the format string, printf expects to see a char* as the corresponding argument. That's why you should pass myptr2 (which is the address of 'A' and from which the subsequent addresses of the string characters can be deduced).
If you pass *myptr2 instead, you are basically passing the character 'A' itself (with no information whatsoever as to where that particular 'A' is — which would have allowed printf to read the rest of the string). Simply put, printf expected a pointer there, so it attempts to treat the corresponding argument as a pointer.
Now notice that the character you passed (by dereferencing a char*, therefore getting a char with the value of 'A') has a size of 1 byte, while a pointer has a size of 4 or 8 bytes typically. This means that printf will most likely read a garbage address made up of a character and some random data found in the stack. There can be no guarantees as to what can happen to the program in this case, so the whole incident invokes undefined behavior.
In your code, you should not dereference myptr2 in second argument of printf, so you have to replace:
printf("Myptr2 points to: %s\n", *myptr2);
with:
printf("Myptr2 points to: %s\n", myptr2);
When using %s with printf, you have to give the pointer on first character of the string.
why this program behaving like this ?
#include <stdio.h>
main()
{
char *p = "Pointers";
printf("%s", p);
}
Output : Pointers
Here i tried to print the string value using "*p" but it crashing while compiling. if i print the value using "p" mean it printing the string instead of address of memory location of "p"
Please help on this
printf expects a pointer for the %s format specifier. If you pass in *p, you are de-referenceing p and actually passing in the first byte of your string (e.g. 'P'). printf is then treating the that first 'P' of your string as a pointer, and it's leading it to an invalid memory location.
As a general rule, in C you don't usually pass strings by value. Instead you pass pointers to strings.
If you want to the print the value of the address of the p variable [vs. what it points to], use:
printf("%p\n",&p);
This will give you the address of p on the stack, which should be a fairly high memory address (e.g. 0x7ffdb4066268).
If you want the address of the string constant pointed to by p [vs. the string], do:
printf("%p\n",p);
You'll get something like 0x400xxx