why *s and *s++ have the same value in the following situation? - c

char *s;
char buf [] = "This is a test";
s = strchr (buf, 't');
if (s != NULL)
printf ("found a 't' at %s\n", s);
printf("%c\n",*s);
printf("%c\n",*s++);
printf("%c\n",*s++);
printf("%c\n",*s++);
printf("%c\n",*s++);
This code outputs:
found a 't' at test
t
t
e
s
t
Program ended with exit code: 0
In my view, *s should be t and *s++ should be e. But why they have same value in this code ?

In the expression *s++, ++ is the post-increment operator. That means following happens, in-order:
The value of s is gotten
Then s is incremented
Then the old value of s is de-referenced
So,
printf("%c\n",*s); // Prints the character at s
printf("%c\n",*s++); // Prints the character at s
// ***and then*** increments it
They will both print the same character.
If you want your example code to behave like you think it should, simply remove the first printf without the post-increment on s:
// s points to the 't'
printf("%c\n",*s++); // Prints 't'. Afterward, s points to the 'e'
printf("%c\n",*s++); // Prints 'e'. Afterward, s points to the 's'
printf("%c\n",*s++); // Prints 's'. Afterward, s points to the 't'
printf("%c\n",*s++); // Prints 't'. Afterward, s points to the NUL terminator

printf("%c\n",*s++);
is (more or less1) equivalent to
printf("%c\n",*s);
s++;
This is why you see 't' printed twice.
The expression i++ evaluates to the current value of i, and as a side effect increments the variable.
1. More or less because s will be updated after *s is evaluated, but before printf is actually called. Exactly when the side effect of ++ is applied isn't specified, apart that it happen before the next sequence point. In this case, a sequence point occurs after all function arguments have been evaluated and before the function is called.

Related

Pointer char output explanation

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

What does while(*pointer) means in C?

When I recently look at some passage about C pointers, I found something interesting. What it said is, a code like this:
char var[10];
char *pointer = &var;
while(*pointer!='\0'){
//Something To loop
}
Can be turned into this:
//While Loop Part:
while(*pointer){
//Something to Loop
}
So, my problem is, what does *pointer means?
while(x) {
do_something();
}
will run do_something() repeatedly as long as x is true. In C, "true" means "not zero".
'\0' is a null character. Numerically, it's zero (the bits that represents '\0' is the same as the number zero; just like a space is the number 0x20 = 32).
So you have while(*pointer != '\0'). While the pointed-to -memory is not a zero byte. Earlier, I said "true" means "non-zero", so the comparison x != 0 (if x is int, short, etc.) or x != '\0' (if x is char) the same as just x inside an if, while, etc.
Should you use this shorter form? In my opinion, no. It makes it less clear to someone reading the code what the intention is. If you write the comparison explicitly, it makes it a lot more obvious what the intention of the loop is, even if they technically mean the same thing to the compiler.
So if you write while(x), x should be a boolean or a C int that represents a boolean (a true-or-false concept) already. If you write while(x != 0), then you care about x being a nonzero integer and are doing something numerical with x. If you write while(x != '\0'), then x is a char and you want to keep going until you find a null character (you're probably processing a C string).
*pointer means dereference the value stored at the location pointed by pointer. When pointer points to a string and used in while loop like while(*pointer), it is equivalent to while(*pointer != '\0'): loop util null terminator if found.
Let's start with a simple example::
int a = 2 ;
int *b = &a ;
/* Run the loop till *b i.e., 2 != 0
Now, you know that, the loop will run twice
and then the condition will become false
*/
while( *b != 0 )
{
*b-- ;
}
Similarly, your code is working with char*, a string.
char var[10] ;
/* copy some string of max char count = 9,
and append the end of string with a '\0' char.*/
char *pointer = &var ;
while( *pointer != '\0' )
{
// do something
// Increment the pointer 1 or some other valid value
}
So, the while loop will run till *pointer don't hit '\0'.
while( *pointer )
/* The above statement means the same as while( *pointer != '\0' ),
because, null char ('\0') = decimal value, numeric zero, 0*/
But the usage can change when you do, while(*pointer != 'x'), where x can be any char. In this case, your first code will exit after *pointer hits the 'x' char but your second snippet will run till *pointer hits '\0' char.
Yes, you can go for it.
Please note that *pointer is the value at the memory location the pointer point to(or hold the address of).
Your *pointer is now pointing to the individual characters of the character array var.
So, while(*pointer) is shorthand usage of the equivalent
while(*pointer!='\0').
Suppose, your string is initialized to 9 characters say "123456789" and situated at an address say addr(memory location).
Now because of the statement:
char *pointer=&var;
pointer will point to first element of string "1234567890".
When you write the *pointer it will retrieve the value stored at the memory location addr which is 1.
Now, the statement:
while(*pointer)
will be equivalent to
while(49)
because ASCII Value of 1 is 49, and condition is evaluated to true.
This will continue till \0 character is reached after incrementing pointer for nine times.
Now, the statement:
while(*pointer)
will be equivalent to
while(0)
because ASCII value of \0 is 0. Thus, condition is evaluated to false and loop stops.
Summary:
In while(condition), condition must be non-zero to continue loop execution. If condition evaluates to zero then loop stops executing.
while(*pointer) will work till the value at memory location being pointed to is a non-zero ASCII value.
Also you can use:
if(*ptr){ //instead of if(*ptr!='\0')
//do somthing
}
if(!*ptr){ //instead of if(*ptr=='\0')
//do somthing
}
*pointer means exactly what it says: "Give me the value that's stored at the place that the pointer points to". Or "dereference pointer" for short. In your concrete example, dereferencing the pointer produces the one of the characters in a string.
while(*pointer) also means exactly what is says: "While the expression *pointer yields a true value, execute the body of the loop".
Since C considers all non-zero values as true, using *pointer in a condition is always equivalent to using the expression *pointer != 0. Consequently, many C programmers omit the != 0 part in order to practice boolean zen.

Don't understand how this for loop works

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.

* Vs ++ precedence in C

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 *

While (*s) - How does this work?

How does this while loop works? When this *s argument terminates?
void putstr (char *s)
{
while (*s) putchar(*s++);
}
So other notable behaviors, arguments for while?
Logical expressions in C evaluate to false if they are 0, otherwise they evaluate to true. Thus your loop will terminate when *s is equal to 0. In the context of a char that is when the null-terminating character is encountered.
Note that ++ has a higher precedence than pointer dereferencing * and so the ++ is bound to the pointer rather than the char to which it points. Thus the body of your loop will call putchar for the character that s points to, and then increment the pointer s.
*s dereferences into a char, which in the loop, a zero (0, or '\0') will act as false, terminating the loop, all other non-zero characters keep it as true.
The char (*s) gets cast to int, for conditions it holds that any integer != 0 is interpreted as true, so the loop ands when a '\0' char is encountered.
Because the loop itself modifies s (with *s++), the while condition can examine it each time around the loop, and it will eventually terminate, when the pointer points to a nul character.
while (*s)
while the character pointed by s is not zero (that is, if we did't reach the end of the string)
putchar(*s++);
it can be thought as
putchar(*s); // write the character pointed by s
s += 1; // go to next one
s is a pointer on a string.
The end of a string is detected by a 0 value

Resources