i was messing around with pointers in C and i came across something like this
#include <stdio.h>
int main() {
char *str2 = "Heyya";
printf("%d %d %s\n", &str2, str2, str2);
return 0;
}
the program ran successfully and gave output
6422300 4214884 Heyya
what I didn't understand is that how come the program printed "Heyya" without using * operator in the second "str2"(the one that is putting value to %s) in the printf function
PS when I run the same with *str2 it gives a segmentation fault
can anyone explain what is happening in the memory?
str2 is a pointer to a character-array which is a literal constant located in the code segment. It is not "allocated." It is simply part of the program's object-code.
Your printf() call now prints the following three things:
The address of the str2 pointer variable itself, which is 6422300.
The address of the character array in the code segment, pointed-to by the pointer at 6422300, which is 4214884.
The bytes that are located at address 4214884, presented as a string.
str2 is a pointer to a location in the memory where "Heyya" was stored.
printf("%s", strpointer) will print the string pointed to by strpointer, until it reaches null terminator, which is what makes it a string. If you add '*' before str2, it will print only the value of the address str2 points at, which is "H". That's happening because '*p' is not a pointer, but it's the actual value of the address of p, but 'p' is a pointer and printf will print the string from the address of which p points to, untill Null Terminator.
For starters this call
printf("%d %d %s\n", &str2, str2, str2);
invokes undefined behavior because there are used incorrect conversion formats for pointers.
A correct call can look like
printf("%p %p %s\n", ( void * )&str2, ( void * )str2, str2);
As for the output then the expression &str2 gives the address of the local variable str2. The expression str2 gives the address of the first character of the string literal "Heyya" that has the static storage location.
If to use the above expression with the conversion format %p then the address will be outputted. If to use the above expression with the conversion format %s then the string first character of which pointed to by the expression str2 will be outputted.
You should understand that the address of the variable str2 itself is different from the address of the string literal pointed to by the variable. That is the expression &str2 yields the address of the variable itself. The expression str2 yields the value stored in the variable that in turn is the address of the first character of the string literal.
As for your question
How is memory allocated in this program?
then in this declaration
char *str2 = "Heyya";
there is created a string literal "Heyya" with the static storage duration and that has the type char[6] (in C++ it has the type const char[6]) and a local variable str2 with the automatic storage duration that is initialized by the address of the first character of the string literal.
printf is a function that let you print something from values given as supplementary arguments. something means some representation from the value.
For instance:
%d takes the corresponding value and write it as a decimal number. You gave first &str2 which is the address of the pointer str2. Second you gave str2 which is the value stored in str2, the address of a C-string. Note, that pointers must be print with %p not %d, but that is almost the same reasoning.
%s is more subtle as it takes an address where a C-string must be stored and print every characters of that C-string.
Related
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.
Why *pointer is an integer but not the string content "Hello from pointer" Thanks!
int main(void) {
char *pointer;
pointer = "Hello from pointer";
printf("*pointer is %d\n", *pointer);
printf("\n");
}
the output is *pointer is 72
It's because the ASCII code for 'H' (which is the first element of the array) is 72. It is completely normal.
Here is the ASCII Code table
pointer = "Hello from pointer"; is pointing to the first letter of this string literal which is H and ASCII Value of 'H' is 72, that's why the output is 72.
In C, a constant character string always represents a pointer to that string. And therefore this statement is valid:
char *pointer = "Hello...";
This statement declares pointer as a pointer to character and assigns to pointer the constant character string "Hello..."
That'ss why when you printf("%d", *pointer); it outputs 72. Because, pointer is pointing to the first character of that constant string literal, which is 'H' and because of the format flag %d in printf() statement, it prints out the ASCII value of 'H', which is 72. Hope you got your explanation.
Here printf("*pointer is %d\n", *pointer); in this line you've used %d format specifier, not %s to print out the string pointer.
Again you should not de-reference the pointer variable when you print string from the string pointer. Try to search and find about String array vs String pointer.
So, the line should be printf("*pointer is %s\n", pointer);
More explanation:
char *pointer = "Hello from pointer";
After compiling this line, "Hello from pointer" will be stored in the memory. And like array variable, the pointer variable will hold the base address of this character array. So, the variable pointer will hold the address of H here.
Thus when you de-reference the pointer variable, it will show the value H. As the format specifier you used is %d, it's printing the integer value (ASCII Value) of the character H (72).
This is caused by a buffer overflow. (Read more here)
The direct answer is because 72 is the integer representation of the character "H" from "Hello from pointer".
Basically, there's two things going on.
1) That variable only expects you to give it one char
2) A pointer only points to a single part in memory, so since strings are treated sort of like "arrays" (per se), you're getting only the first value in the "array"
So if you were to print *pointer[1] you would get e. So the idea is to know the length of your string so you can safely determine how much space you need.
But remember, memory is volatile, so even though whatever compiler you use will open up a certain amount of "stack memory", you can overflow that with a long string.
If you don't know the length of your string and/or your string is very long, you can dynamically allocate it with malloc() and free().
I was trying to learn pointers and I wrote the following code to print the value of the pointer:
#include <stdio.h>
int main(void) {
char *p = "abc";
printf("%c",*p);
return 0;
}
The output is:
a
however, if I change the above code to:
#include <stdio.h>
int main(void) {
char *p = "abc";
printf(p);
return 0;
}
I get the output:
abc
I don't understand the following 2 things:
why did printf not require a format specifier in the second case? Is printf(pointer_name) enough to print the value of the pointer?
as per my understanding (which is very little), *p points to a contiguous block of memory that contains abc. I expected both outputs to be the same, i.e.
abc
are the different outputs because of the different ways of printing?
Edit 1
Additionally, the following code produces a runtime error. Why so?
#include <stdio.h>
int main(void) {
char *p = "abc";
printf(*p);
return 0;
}
For your first question, the printf function (and family) takes a string as first argument (i.e. a const char *). That string could contain format codes that the printf function will replace with the corresponding argument. The rest of the text is printed as-is, verbatim. And that's what is happening when you pass p as the first argument.
Do note that using printf this way is highly unrecommended, especially if the string is contains input from a user. If the user adds formatting codes in the string, and you don't provide the correct arguments then you will have undefined behavior. It could even lead to security holes.
For your second question, the variable p points to some memory. The expression *p dereferences the pointer to give you a single character, namely the one that p is actually pointing to, which is p[0].
Think of p like this:
+---+ +-----+-----+-----+------+
| p | ---> | 'a' | 'b' | 'c' | '\0' |
+---+ +-----+-----+-----+------+
The variable p doesn't really point to a "string", it only points to some single location in memory, namely the first character in the string "abc". It's the functions using p that treat that memory as a sequence of characters.
Furthermore, constant string literals are actually stored as (read-only) arrays of the number of character in the string plus one for the string terminator.
Also, to help you understand why *p is the same as p[0] you need to know that for any pointer or array p and valid index i, the expressions p[i] is equal to *(p + i). To get the first character, you have index 0, which means you have p[0] which then should be equal to *(p + 0). Adding zero to anything is a no-op, so *(p + 0) is the same as *(p) which is the same as *p. Therefore p[0] is equal to *p.
Regarding your edit (where you do printf(*p)), since *p returns the value of the first "element" pointed to by p (i.e. p[0]) you are passing a single character as the pointer to the format string. This will lead the compiler to convert it to a pointer which is pointing to whatever address has the value of that single character (it doesn't convert the character to a pointer to the character). This address is not a very valid address (in the ASCII alphabet 'a' has the value 97 which is the address where the program will look for the string to print) and you will have undefined behavior.
p is the format string.
char *p = "abc";
printf(p);
is the same as
print("abc");
Doing this is very bad practice because you don't know what the variable
will contain, and if it contains format specifiers, calling printf may do very bad things.
The reason why the first case (with "%c") only printed the first character
is that %c means a byte and *p means the (first) value which p is pointing at.
%s would print the entire string.
char *p = "abc";
printf(p); /* If p is untrusted, bad things will happen, otherwise the string p is written. */
printf("%c", *p); /* print the first byte in the string p */
printf("%s", p); /* print the string p */
why did printf not require a format specifier in the second case? Is printf(pointer_name) enough to print the value of the pointer?
With your code you told printf to use your string as the format string. Meaning your code turned equivalent to printf("abc").
as per my understanding (which is very little), *p points to a contiguous block of memory that contains abc. I expected both outputs to be the same
If you use %c you get a character printed, if you use %s you get a whole string. But if you tell printf to use the string as the format string, then it will do that too.
char *p = "abc";
printf(*p);
This code crashes because the contents of p, the character 'a' is not a pointer to a format string, it is not even a pointer. That code should not even compile without warnings.
You are misunderstanding, indeed when you do
char *p = "Hello";
p points to the starting address where literal "Hello" is stored. This is how you declare pointers. However, when afterwards, you do
*p
it means dereference p and obtain object where p points. In our above example this would yield 'H'. This should clarify your second question.
In case of printf just try
printf("Hello");
which is also fine; this answers your first question because it is effectively the same what you did when passed just p to printf.
Finally to your edit, indeed
printf(*p);
above line is not correct since printf expects const char * and by using *p you are passing it a char - or in other words 'H' assuming our example. Read more what dereferencing means.
why did printf not require a format specifier in the second case? Is printf(pointer_name) enough to print the value of the pointer?
"abc" is your format specifier. That's why it's printing "abc". If the string had contained %, then things would have behaved strangely, but they didn't.
printf("abc"); // Perfectly fine!
why did printf not require a format specifier in the second case? Is printf(pointer_name) enough to print the value of the pointer?
%c is the character conversion specifier. It instructs printf to only print the first byte. If you want it to print the string, use...
printf ("%s", p);
The %s seems redundant, but it can be useful for printing control characters or if you use width specifiers.
The best way to understand this really is to try and print the string abc%def using printf.
The %c format specifier expects a char type, and will output a single char value.
The first parameter to printf must be a const char* (a char* can convert implicitly to a const char*) and points to the start of a string of characters. It stops printing when it encounters a \0 in that string. If there is not a \0 present in that string then the behaviour of that function is undefined. Because "abc" doesn't contain any format specifiers, you don't pass any additional arguments to printf in that case.
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
I am new to C language. Recently I have come across several problems regarding pointers. Would like to seek your help. Thank you very much~
Below is a code block:
char *a[2];
a[0] = "blah";
a[1] = "hmm";
printf("%s %d\n", a[0],a[0]);
printf("%s %d\n", a[1], a[1]);
Output of the above codes is "blah", address of a[0],"hmm" and address of a[1].
First question is: a[0] is supposed to be a pointer, which should contain an address. But here a[0] is assigned with a string, which is strange. Why this works?
Second question is: a[0] is a pointer, therefore printf("%d",a[0]) will naturally print the address of a[0]. However, printf("%s",a[0]) prints "blah", which is the string stored in the address whose address value is equal to the value stored in a[0]. Intuitively I think the correct syntax to print the string is to use printf("%s",*(a[0])) , which turns out to be execution error. So why printf("%s",a[0]) gives the desired string result?
Looking forward to your answers and really appreciate your help~
printf("%s %d\n", a[0],a[0]);
You should use %p to print pointers. %d is to print integers.
a[0] is supposed to be a pointer, which should contain an address. But here a[0] is assigned with a string, which is strange. Why this works?
Yes. a[0] is supposed to be a pointer, which should contain an address. Assigning a[0] to a string works because string constant is a pointer to it's first member. i.e. "blah" is a pointer to b
To verify:
printf("%p\n", "blah");
a[0] is a pointer, therefore printf("%d",a[0]) will naturally print the address of a[0]. However, printf("%s",a[0]) prints "blah", which is the string stored in the address whose address value is equal to the value stored in a[0].
printf("%p", a[0]) will print the value of a[0] which is an address and printf("%s", a[0]) will print a string stored linearly starting from address a[0]. This is because of format specifier used.
%p says print the value as address (pointer) wheres %s says print all the characters stored starting from a[0] till \0 character encounters.
Intuitively I think the correct syntax to print the string is to use printf("%s",*(a[0])) , which turns out to be execution error.
a[0] is a pointer, an address. We have character b from "blah" stored at that address. So the type of *(a[0]) is char wheres "%s" expects type char * (a pointer to character). So type mismatch.
To get the clear idea:
printf("%c",*(a[0]));
This will print the character stored at a[0] as we are dereferencing a[0] using * operator.
A string literal is actually an array of characters, which includes the terminating null character. And as all arrays, the string literal array can decay to a pointer to its first element.
And all string handling in C is using pointers to the first character, and then simply just increase the "index" until it finds the terminating character.
Also note that using the "%d" format for printing pointers is undefined, you should be using the "%p" format.