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.
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 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.
I have been studying strings in C, and have been faced with the following problem, in the following code:
#include <stdio.h>
int main()
{
char *p = "foo";
printf("%p\t%p\t%p",&p[0],p,p[0]);
return 0;
}
And i have the following output:
00403024 00403024 00000066
Process returned 0 (0x0) execution time : 0.057 s
Press any key to continue.
Since p points to the first element of the string, shouldn't p[0] point to the same addres as p (and by consequence, &p[0])?
p[0] is not a pointer, it's a char.
Since you're asking for %p in your format string it gets force-cast to an invalid pointer with the value 0x00000066, which is just the ASCII value of f, the first character in the string.
If you turn on all the warnings your compiler offers you may see one that highlights this conversion and how it's a potential error.
p is of type char*. &p[0] is like &(*(p + 0)) which is to say you de-reference it to a char, then turn it back into a pointer with &. The end result is the same as the original.
You got it almost right. A pointer just stores the address of the pointee that it points to. So outputting p outputs the address of the string.
So what does [x] do when applied to such an address p? It does *(p+x); that is, it evaluates to the value that is stored at this address plus x. So in the case of p[0], you get the ASCII value of the char 'f', which is 66.
Taking the address of that again by prefixing with & gives you the address where it is stored. This is just the address of the original string, of course, because as you observed, the address of the string coincides with the address of its first element.
I was trying to learn strings in C when I came across this code.
#include <stdio.h>
int main(){
char s[] = "Hello world";
printf("%s" , s);
printf("%s" , &s);
return 0;
}
Both gave Hello World as output. According to my understanding, this output is Ok for First case. How is it working for the second one? Please clarify.
Taking the address of an array is the same as taking the address of it's first element. When the array's name is used, then it also decays to the address of it's first element- so the expressions s and &s yield the same result.
s returns the address of the first item in the array and &s returns the address of the array itself -- these happen to be the same.
In general, if you wish to be more explicit, the expression &s[0] can also be used to return the address of the first item.
s and &s return the same address and hence. This address is the location where "H" from "Hello world" is stored.
Because,
The name of the array decays to the address of the first element in an array &
The address of first element is same as address of the array.
Just for what it may be worth, if you want to get technical, your second version:
printf("%s" , &s);
has undefined behavior, and only works by accident. By explicitly taking the address, you're getting the address of the array (which is fine) but the result has the type "pointer to array of 12 characters", rather than the type "pointer to char", as required for printf's %s conversion. Since the types don't match, the result is undefined behavior.
In reality, however, that's purely a technicality -- the code will work just fine on every implementation of C of which I'm aware.
If you wanted to demonstrate that the difference exists, you could do so pretty easily though. For example:
char string[] = "hello world";
printf("without &: %p, %p\n", (void *)string, (void *)(string+1));
printf("with &: %p, %p\n", (void *)&string, (void *)(&string+1));
In the first case, string decays to a pointer to char, so on the first line, the second pointer will be exactly one greater than the first. On the second line, we're adding one to a pointer to an array of characters, so when we add one, it'll actually add the size of the array. Running this on my machine, I get results like this:
without &: 0038F96C, 0038F96D
with &: 0038F96C, 0038F978
char s[] is similar to char *s that is a charecter pointer that points to the first element of the array (it contains the address of the first element stored).
we can also store strings by storing the address of the first character. during the time of execution, computer start taking characters from that address one by one and make a string until it reaches a null character('\0').
in the above example 's' and '%s' represents the same value (the address of the starting character) hope you will get it.
if you use char s[10] (fixed length array) you will understand everything.
s is equivalent to &s[0] so we are passing address of s[0] not the address of pointer that is pointing to s[0] so it will print Hellow world in second case.
s is name of array not a pointer.