char alpha[] = "abcdefghi";
char ch[80], *pch = &ch[0];
strcpy(ch, alpha);
putchar(*pch++);
putchar((*pch)++);
putchar(*++pch);
putchar(++(*pch));
printf("\n%s", ch);
Why does the putchar function print 'a' 'b' 'c' and 'd' respectively?
Why does printf("\n%s", ch); print acddefghi?
I am really bad with pointer stuff.
OK, I will try to explain this as simply as I can.
When you do: putchar(*pch++) what you say is 'print that character of the address that pch points to and then increment the pch to point to the next address'. Essentially, before the first putchar(), *pch = 'a' and after *pch = 'b'(because pch points now to ch[1]).
Now, in the second putchar() what you say is: 'print the character in the address that pch points to and then increment the value of the CHARACTER, in that address, by 1'. So, instead of doing what you did in the second putchar(), you could replace this line whith these two lines:putchar(*pch); // 'b'
*pch += 1; // see, you increment the value(notice the *), not the pointer.
However, because as I said, it increments the character AFTER the second putchar(), it just prints what it was which is 'b'. So, just to clear, after the second putchar(), ch[0] = 'a'(we did not change anything in this value)
and ch[1] = 'c'(we incremented the value of the character by 1 and 'b' + 1 = 'c'). The rest is unchanged, so ch[2] = 'c', ch[3] = 'd' and so on.. but pch points to ch[1]
Now, in the third putchar(), you do something similar with the first except that you first increment the address that pch points and then print the value of this address.So, you could replace the third putchar() with these two lines:pch++; // increment the pointer by one, it now points to ch[2], which is 'c'(it remained unchanged)
putchar(*pch); // 'c'
So, after the third putchar(), ch[0] = 'a'(remained unchanged), ch[1] = 'c'(changed in the second putchar()), ch[2] = 'c'(remained unchanged)
Finally, in the last putchar(), what you do is similar to the second except that you increment the value of the CHARACTER that pch points to before you print it.
Remember that pch points to ch[2]
So, you could replace the last putchar() with these two lines:
*pch += 1; // 'c' + 1 = 'd'
putchar(*pch); // 'd'
So, after the 4 putchars, ch[0] = 'a'(it remained unchanged), ch[1] = 'c'(changed in the second putchar()), ch[2] = 'd'(changed in the fourth putchar()) and ch[3] = 'd'(it remained unchanged) and the rest of the string remains unchanged, and I think it is now obvious why you get the result you get from printf().
ch is an array of characters. In C an array is just a pointer to the first element in the array. That makes ch a pointer to a char (char *) as well. putchar prints a single character when you pass it a character to print. *pch++ says 'use the character at this address' then increment the address to point at the next char. printf prints the whole string because of the format specifier "\n%s" which tells printf to print the array of characters (a string if you will) which is found at the address ch. Which we know from above is an array of characters. Hope this helps.
Dereferences the pointer and returns back the value 'a', then the pointer is incremented by 1.
putchar(*pch++);
Same as the first explanation above. Returns back 'b'.
putchar((*pch)++);
Increments the pointer then dereference it, the value returned back is 'c'.
putchar(*++pch);
Same as the previous, returns back the value of 'd'.
putchar(++(*pch));
Pointer increments/decrements are based on the type of the variable that is declared.
Since ch is declared an array of characters, printf prints out the entire contents of that said variable.
strcpy(ch, alpha);
Copy the contents of alpha into an array ch, i.e. "abcdefghi"
All "arrays" decay into pointers pointing to the first element of type T.
(They are not really arrays!)
value of address means address location
value of data means the value in that address
Try to think it in this way:
Whatever follows after * is an address.
Eg: *x, here the value of x is an address.
And when you combine * and x i.e. *x, it represents the value at that address.
Whenever you do *p++, the value of p( which is address value) post increments by depending on the data type of the pointer. So, it will point to the next block of address. It won't increment the value of data.
In C, the char pointer points to address of first array and prints the entire array until a null character is received.
Watch lectures on pointer. You will be clear.
*pch++ print current pointer value and increments pointer
(*pch)++ print current pointer value, and increments that value
*++pch It increments pointer and print value of new pointer
++(*pch) It increments value of current pointer and then print that new value
putchar(*pch++); // It prints ch[0], print and increments pointer
putchar((*pch)++); // It prints ch[1], print and increment value;
putchar(*++pch); // It prints ch[2], pointer increments and print
putchar(++(*pch)); // It prints ch[2]+1, increment value and print
Related
I got this code snippet from here:
int main(int argc, char *argv[])
{
for (int i = 1; i < argc; ++i) {
char *pos = argv[i];
while (*pos != '\0') {
printf("%c\n", *(pos++));
}
printf("\n");
}
}
I have two questions:
Why are we starting the iterations of for loop at i=1, why not
start it at i=0, especially when we are ending the iterations at
i<argc and Not at i<=argc?
The second, third and fourth last lines of code! In char *pos =
argv[i];, we declare a pointer type variable and assign it a
pointer to a commandline parameter passed when running the program.
Then in while (*pos != '\0'), *pos dereferences the pointer
stored in pos, so *pos contains the actual value pointed by the
pointer stored in pos.
Then in printf("%c\n", *(pos++));, we have *(pos++), and
that is the actual question: (a) Why did he increment pos, and
(b) what is the meaning of dereferencing (pos++) with the
dereference operator *?
Why are we starting the iterations of for loop at i=1, why not start it at i=0, especially when we are ending the iterations at
i
We start at 1 because argv[0] holds the name of the program itself which we don't care about. Ignoring the first element of an array does not move the index of the last array.
We have argc elements stored in argv[]. Therefore we mustn't run until i==argc but need to stop one element earlier, just as with every other array.
The second, third and fourth last lines of code! In char *pos = argv[i];, we declare a pointer type variable and assign it a pointer
to a commandline parameter passed when running the program.
Correct. pos is a pointer and points to the first string passed via command line.
Then in while (*pos != '\0'), *pos dereferences the pointer stored in
pos, so *pos contains the actual value pointed by the pointer stored
in pos.
*pos contains the first character of the string we are currently inspecting.
Then in printf("%c\n", *(pos++));, we have *(pos++), and that is the
actual question: (a) Why did he increment pos, and (b) what is the
meaning of dereferencing (pos++) with the dereference operator *?
You have 2 things here:
1. (pos++): pos is a pointer to char and with ++ increment the pointer to point to the next element, i.e. to the next char after taking its value.
2. The value of pos (before the post-increment) is taken and dereferenced to read the char at that position.
As a result the while loop will read all characters, while the for loop handles all strings.
For the first part,
Why are we starting the iterations of for loop at i=1, why not start it at i=0, especially when we are ending the iterations at i<argc and Not at i<=argc?
Because, for hosted environment, argv[0] represents the executable name. Here, we're only interested in supplied command line arguments other than the executable name itself.
Quoting C11, chapter ยง5.1.2.2.1
If the value of argc is greater than zero, the string pointed to by argv[0]
represents the program name; [....] If the value of argc is
greater than one, the strings pointed to by argv[1] through argv[argc-1]
represent the program parameters.
Point to note: using i<=argc as the loop condition would be wrong, as C arrays use 0-based indexing.
For the second part,
(a) Why did he increment pos, and (b) what is the meaning of dereferencing (pos++) with the dereference operator *?
*(pos++), can also be read as *pos; pos++; which, reads the current value from the memory location pointed to by pos and then advances pos by one element.
To elaborate, at the beginning of each iteration of the for loop, by saying
char *pos = argv[i];
pos holds the pointer to the starting of the string which holds the supplied program parameter and by continuous increment (upto NULL), we're basically traversing the string and by dereferencing, we're reading the value at those locations.
Just for the sake of completeness, let me state, that the whole for loop body
char *pos = argv[i];
while (*pos != '\0') {
printf("%c\n", *(pos++));
can be substituted using
puts(argv[i]);
Why are we starting the iterations of for loop at i=1, why not start
it at i=0, especially when we are ending the iterations at i
Because first parameter is name of the program - and it seems author is not interested in it.
Second case is basically similar to the following (argv[i] basically being a char *):
So you have something like this:
char * c = "Hello"
and then char * p = c;
Now you have
+------------------+
| H e l l o /0 |
| ^ |
| | |
+------------------+
|
|
+
p
When you do p++ you have
+------------------+
| H e l l o /0 |
| ^ |
| | |
+------------------+
|
+-+
+
p
If you do now *p - the value you get is 'e'.
*(p++) is basically same as above two steps, just due to post increment, first the value where p points will be retrieved (before increment), and then p will advance.
Then in printf("%c\n", *(pos++));, we have *(pos++), and that is the
actual question: (a) Why did he increment pos, and (b) what is the
meaning of dereferencing (pos++) with the dereference operator *?
So in the while loop the author is traversing through the whole string until he meets null terminator '\0' and printing each character.
This on the other hand is repeated for each parameter in argv using the for loop.
Why are we starting the iterations of for loop at i=1, why not start
it at i=0, especially when we are ending the iterations at i < argc and
Not at i <= argc?
Note that the argc contains the name of the program being executed too which will be the first (given the number zero) thing to be counted. So the actual arguments starts from 1 and ends at total - 1
A note here, the command line arguments are stored in array of pointer to char, ie
argv[0] -> "YourFirstArguement"
argv[1] -> "YourSecondArguement"
.
.
argv[argc-1] -> "YourLastArguement" //Remember argc-1 is the last argument
and so. Note that each of the argument is a null terminated string
So in
char *pos = argv[i]; // Create another pointer to each string
while (*pos != '\0') {
printf("%c\n", *(pos++)); // Note %c, you're printing char by char.
}
You're just printing character by character using the format specifier %c in printf. So you need to dereference character by character in the while loop and this answers
a) Why did he increment pos, and
b) what is the meaning of dereferencing (pos++) with the dereference operator *?
code example like this:
#include<stdio.h>
void main()
{
char *s={"abcd"};
do {
printf("%d\n",++s);
} while(*s);
}
Where does the pointer s point when the loop do ends?How does it work?
In C, zero is equivalent to false. So when *s points to the terminator character in the string (a zero), the loop stops.
"abcd" is stored in memory in 5 consecutive bytes: 'a' 'b' 'c' 'd' '\0'.
The last byte, zero, terminates the loop since zero is false in C.
First of all, you should not use %d for formatting a pointer, it is for integers, not for pointers. Use %p instead.
This line-
char *s={"abcd"};
initializes the string with '\0' as the last character.
Your programs loops through each character (from 2nd to last) of the string an prints the address of where they are stored in the memory. Since it is a do-while loop, the condition checking is done after the execution of the body of the loop.
NOTE: It does NOT print the address of the first character because-
printf("%d\n",++s);
this line (due to prefix increment) increments the pointer to the next character before passing its value to printf. So when the body of the loop is executed for the first time, the address of the second character(b) is printed.
Now the condition part of the loop checks whether character at pointed by s (the character can be referred to by *s) is non-zero.
As the string has '\0' as the last character (which has an integer value of 0), the loop terminates when it reaches the last character.
The output of your program (with %d changed to %p) will be something like but NOT exactly same as-
0x40061d
0x40061e
0x40061f
0x400620
Note that only 4 addresses are printed (from 'b' to '\0', the address of 'a' is not printed). To do that you should try this-
#include<stdio.h>
main()
{
char *s={"abcd"};
do {
printf("%p\n",s++);
} while(*s);
printf("%p\n", s); // to print the address of the '\0' character.
}
Can someone explain how this loop works? The entire function serves to figure out where in hash to place certain strings and the code is as follows:
//determine string location in hash
int hash(char* str)
{
int size = 100;
int sum;
for(; *str; str++)
sum += *str;
return sum % size;
}
It seems to iterate over the string character by character until it hits null, however why does simple *str works as a condition? Why does str++ moves to the next character, shouldn't it be something like this instead: *(str+i) where i increments with each loop and moves "i" places in memory based on *str address?
In C, chars and integers implicitly convert to booleans as: 0 - false, non-zero - true;
So for(; *str; str++) iterates until *str is zero. (or nul)
str is a pointer to an array of chars. str++ increments this pointer to point to the next element in the array and therefore the next character in the string.
So instead of indexing by index. You are moving the pointer.
The condition in a for loop is an expression that is tested for a zero value. The NUL character at the end of str is zero.
The more explicit form of this condition is of course *str != '\0', but that's equivalent since != produces zero when *str is equal to '\0'.
As for why str++ moves to the next character: that's how ++ is defined on pointers. When you increment a char*, you point it to the next char-sized cell in memory. Your *(str + i) solution would also work, it just takes more typing (even though it can be abbreviated str[i]).
This for loop makes use of pointer arithmetic. With that you can increment/decrement the pointer or add/substract an offset to it to navigate to certain entries in the array, since array are continuous blocks of memory you can do that.
str points to a string. Strings in C always end with a terminating \0.
*str dereferences the actual pointer to get the char value.
The for loop's break condition is equivalent to:
*str != '\0'
and
str++
moves the pointer forward to next element.
The hole for-loop is equivalent to:
int len = strlen(str);
int i;
for(i = 0; i < len; i++)
sum += str[i];
You could also write is as while-loop:
while(*str)
sum += *str++;
Why does str++ moves to the next character, shouldn't it be something like this
instead: *(str+i) where i increments with each loop and moves "i" places in
memory based on *str address?
In C/C++, string is a pointer variable that contains the address of your string literal.Initially Str points to the first character.*(str) returns the first character of string.
Str++ points to second charactes.Thus *(str) returns the second character of the string.
why does simple *str works as a condition?
Every c/c++ string contains null character.These Null Characters signify the end of a character string in C. ASCII code of NUL character is 0.
In C/C++,0 means FALSE.Thus, NUL Character in Conditional statement
means FALSE Condition.
for(;0;)/*0 in conditions means false, hence the loop terminates
when pointer points to Null Character.
{
}
It has to do with how C converts values to "True" and "False". In C, 0 is "False" and anything else is "True"
Since null (the character) happens to also be zero it evaluates to "False". If the character set were defined differently and the null character had a value of "11" then the above loop wouldn't work!
As for the 2nd half of the question, a pointer points to a "location" in memory. Incrementing that pointer makes it point to the next "location" in memory. The type of the pointer is relevant here too because the "Next" location depends on how big the thing being pointed to is
When the pointer points to a null character it is regarded as false. This happens in pointers. I don't know who defined it, but it happens.
It may be just becuase C treats 0 as false and every other things as true.
For example in the following code.
if(0) {
puts("true");
} else {
puts("false");
}
false will be the output
The unary * operator is a dereference operator -- *str means "the value pointed to by str." str is a pointer, so incrementing it with str++ (or ++str) changes the pointer to point to the next character. So it is the correct way to increment in the for loop.
Any integral value can be treated as a Boolean. *str as the condition of the for loop takes the value pointed to by str and determine if it is non-zero. If so, the loop continues Once it hits a null character, it terminates.
I am not able to understand the output of the following C code :
#include<stdio.h>
main()
{
char * something = "something";
printf("%c", *something++); // s
printf("%c", *something); // o
printf("%c", *++something); // m
printf("%c", *something++); // m
}
Please help :)
See http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence for details
printf("%c", *something++);
Gets the char at *something and then increments it ('s')
printf("%c", *something);
Just get the char (now the second, due to the increment in the last statement ('o')
printf("%c", *++something);
increment and then get the char of the new position ( 'm' )
printf("%c", *something++);
Gets the char at *something and then increments it ('m')
It is pretty simple.
char * something = "something";
Assignment of pointer.
printf("%c\n", *something++);//equivalent to *(something++)
Pointer is incremented but the value before increment is dereferenced ans it is post-increment.
printf("%c\n", *something);//equivalent to *(something)
Pointer is now pointing to 'o' after increment in the previous statement.
printf("%c\n", *++something);//equivalent to *(++something)
Pointer is incremented to point to 'm' and dereferenced after incrementing the pointer as this is pre-increment.
printf("%c\n", *something++);//equivalent to *(something++)
Same as the first answer.
Also notice '\n' at the end of every string in printf. It makes the output buffer flush and makes the line print. Always use a \n at the end of your printf.
You may want to look at this question as well.
// main entrypoint
int main(int argc, char *argv[])
{
char * something = "something";
// increment the value of something one type-width (char), then
// return the previous value it pointed to, to be used as the
// input for printf.
// result: print 's', something now points to 'o'.
printf("%c", *something++);
// print the characer at the address contained in pointer something
// result: print 'o'
printf("%c", *something);
// increment the address value in pointer something by one type-width
// the type is char, so increase the address value by one byte. then
// print the character at the resulting address in pointer something.
// result: something now points at 'm', print 'm'
printf("%c", *++something);
// increment the value of something one type-width (char), then
// return the previous value it pointed to, to be used as the
// input for printf.
// result: print 's', something now points to 'o'.
printf("%c", *something++);
}
Result:
somm
always use the clockwise rule clockwise rule
printf("%c\n", *something++);
according to the rule you will first encounter * so get the value then ++ means increment
in the 3rd case printf("%c\n", *something++);
so according to the image increment the value ++ and then get the value *
The code snippet is:
char c[]="gate2011";
char *p=c;
printf("%s",p+p[3]-p[1]);
The output is:
2011
Can anyone explain how it came?
-----Thanks in advance-----
Going through each line in turn:
char c[] = "gate2011";
Let's assume that array c is located at memory address 200.
char *p = c;
p is now a pointer to c. It therefore points to memory address 200. The actual content of p is "200", indicating the memory address.
printf("%s", p + p[3] - p[1]);
The value of p is 200 when we treat it like a pointer. However, we can also treat it like an array. p[3] gets the value of the 4th item in the string, which is "e". C stores characters as their ASCII value. The ASCII value of "e" is 101.
Next, we get the value of p[1]. p[1] == "a", which has an ASCII value of 97. Substituting these into the function:
printf("%s", 200 + 101 - 97);
That evaluates to:
printf("%s", 204);
At memory address 204, we have the string "2011". Therefore, the program prints "2011".
I'm not sure why you'd want to do something like this, but anyway, this is what's happening.
p + p[3] - p[1]
Here you are taking a value of one pointer, and adding the value of the char at position 3, and then subtracting the value of the char at position 1. The char values are being implicitly cast to numerical values before doing the addition and subtraction.
If p is location 1000, then the sum 1000 + 101(ASCII for e) - 97(ASCII for a) will be made. Therefore the result is a pointer to location 1004 in memory. The %s in the printf then subsitutes the string that starts at this location, and ends with the special character '\0'. So the string is effectively clipped to "2011" (the first 4 letters are missed because 101 - 97 = 4).
If this still doesn't make sense, I'd suggest you have a good look at how arrays in C work.
What have you expected? Why not?
p[3]-p[1] = 'e'-'a' = 4
p+4 = "2011"