please i can't understand the while loop , why the loop show A two time and not one
char *s,*t;
s="ABC";
t="AA";
do {printf("A");}
while(*s++==*t++);
printf("%d %d",*s-*t);
In your code
printf("%d %d",*s-*t);
invokes undefined behavior as you're not supplying enough argument to sate the supplied format specifiers.
why the loop show A two time and not one?
The first time after the do, the print occurs unconditionally. Then the test occurs, and the condition is true (A == A). So the loop starts again, printing A the second time. After that, the test occurs again, and the condition is false (D != A), so the loop terminates.
It prints 67 because (a) you are using the %d decimal number output format, and (b), after the loop ends, *s == 'C' and *t == '\0', and the difference of their ASCII values is 67.
A do...while loop always runs at least once. So on the first iteration, A gets printed. In the condition s points to the first character in its string (A), and t points to the first character in its string ( also A). So it compares ('A'=='A') which is true, then s and t are both incremented to point to the second character in each string (A and B respectively).
On the second iteration, another A gets printed. In the condition it compares ('B'=='A') which is false, then s and t are both incremented to point to the third character in each string. Since the t string only contains two characters, t actually points to the NULL byte at the end of the string.
In the printf, it subtracts the value pointed to by s (C) by the value pointed to by t (a NULL byte, which in your implementation is 0). The ASCII value of C is 67, and 67 - 0 = 0, so 67 is printed.
Related
#include<stdio.h>
int main()
{
char *s = "Abc";
while(*s)
printf("%c", *s++);
return 0;
}
I have seen this (on a site) as a correct code but I feel this is undefined behavior.
My reasoning:
Here s stores the address of the string literal Abc. So while traversing through the while loop :
Iteration - 1:
Here *(s++) increments the address stored in s by 1 and returns the non-incremented address (i.e the previous/original value of s). So, no problem everything works fine and Abc is printed.
Iteration - 2:
Now s points to a completely different address (which may be either valid or not). Now when trying to perform while(*s) isn't it undefined behavior ?
Any help would be really appreciated!
No. There's no undefined behaviour here.
*s++ is evaluated as *(s++) due to higher precedence of postfix increment operator than the dereference operator. So the loop simply iterates over the string and prints the bytes and stop when it sees the null byte.
Now s points to a completely different address (which may be either valid or not). Now when trying to perform while(*s) isn't it undefined behavior ?
No. In the first iteration s points to the address at the char A and at b in the next and at c in the next. And the loop terminates when s reaches the null byte at end of the string (i.e. *s is 0).
Basically, there's no modification of the string literal. The loop is functionally equivalent to:
while(*s) {
printf("%c", *s);
s++;
}
Iteration - 1:
Here *(s++) increments the address stored in s by 1 and returns the non-incremented address (i.e the previous/original value of s). So, no problem everything works fine and Abc is printed.
No, “Abc” is not printed. %c tells printf to expect a character value and print that. It prints a single character, not a string. Initially, s points to the first character of "Abc". s++ increments it to point to the next character.
Iteration - 2:
Now s points to a completely different address (which may be either valid or not). Now when trying to perform while(*s) isn't it undefined behavior ?
In iteration 2, s is pointing to “b”.
You may have been thinking of some char **p for which *p had been set to a pointer to "abc". In that case, incrementing p would change it to point to a different pointer (or to uncontrolled memory), and there would be a problem. That is not the case; for char *s, s points to a single character, and incrementing it adjusts it to point to the next character.
Now s points to a completely different address
Indeed, it is a completely different but well defined address. s referenced the next char of the string literal. So it just adds 1 to the pointer.
Because string literal is nul (zero) terminated the while loop will stop when s will reference it.
There is no UB.
I have been studying the C language for the last few months. I'm using a book and I have this exercise:
char vector[N_STRINGS][20] = {"ola", "antonio", "susana"};
char (*ptr)[20] = vector;
char *p;
while(ptr-vector<N_STRINGS)
{
p = *ptr;
while(*p)
putchar(*p++);
putchar('\n');
ptr++;
}
I understand everything expect the while(*p)! I can't figure out what the while(*p) is doing.
The variable p in your code is defined as a pointer to a char. The get the actual char value that p points to, you need to dereference the pointer, using the * operator.
So, the expression in your while loop, *p evaluates - at the beginning of each loop - to the char variable that p is currently pointing to. Inside the loop, the putchar call also uses this dereference operator but then increments the pointer's value so, after sending that character to the output, the pointer is incremented (the ++ operator) and it then points to the next character in the string.
Conventionally (in fact, virtually always), character strings in C are NUL-terminated, meaning that the end of the string is signalled by having a character with the value of zero at the end of the string.
When the while loop in your code reaches this NUL terminator, the value of the expression *p will thus be ZERO. And, as ZERO is equivalent to a logical "false" in C (any non-zero value is considered "true"), the while loop will end.
Feel free to ask for further clarification and/or explanation.
From the C Standard (6.8.5 Iteration statements)
4 An iteration statement causes a statement called the loop body to be
executed repeatedly until the controlling expression compares equal to
0.
In this part of the program
p = *ptr;
while(*p)
//…
the pointer p points to the first character of a current string. String in C is a sequence of characters terminated by the zero character '\0'.
So let's for example the pointer initially points to the first character of the string "ola". The string is represented in the corresponding character array like
{ 'o', 'l', 'a', '\0' }
The condition in the loop
while(*p)
may be rewritten like
while(*p != 0 )
So the loop will be executed for all characters of the string except the last zero-terminated character and there will be outputted the first three characters of the string.
Pay attention to that (6.5.9 Equality operators)
3 The == (equal to) and != (not equal to) operators are analogous to
the relational operators except for their lower precedence.108) Each
of the operators yields 1 if the specified relation is true and 0 if it
is false. The result has type int. For any pair of operands, exactly
one of the relations is true.
I can't understand why the following code outputs 10.
What I understand is that !printf("0") means !0, which is TRUE. So why doesn't the code print "Sachin"
#include <stdio.h>
int main() {
for (printf("1"); !printf("0"); printf("2"))
printf("Sachin");
return 0;
}
Output
10
let's analyze this side-effect loop statement:
for(printf("1"); !printf("0"); printf("2"))
The first statement is executed, always (init condition), yieiding 1
Then the condition is tested: !printf("0") prints 0, then since printf returns 1 because it just prints 1 character, the negation returns 0 and the loop is never entered because the condition is false right from the start. So neither 2 or Sachin are printed.
Of course, this code isn't practical, almost unreadable. So don't ever do things like this (puts("10"); is a good alternative for instance).
more on the return value of printf (that is often ignored):
Upon successful return, these functions return the number of characters printed (excluding the null byte used to end output to strings).
(from https://linux.die.net/man/3/printf)
If you look at the man printf reference on google, you'll see that this function returns the number of written bytes.
Here your condition is !printf("0"), in other words : "as long as the return of printf is not existing (or equal 0), do something. But you print the character '0' so printf actually return 1 so your condition is false.
Now WHY it prints 10 :
The first printf("1") prints 1.
Your condition is tested at least once, so the second printf("0") occurs one time (it prints 0)
printf("1")
prints 1 and it return number of characters which is 1
printf("0")
prints 0 and it return number of characters which is 1
!1 means !(true) = false so execution will stop and you will see 10 as output.
I am writing the strcat function
/*appends source string to destination string*/
#include <stdio.h>
int main()
{
char srcstr[100], deststr[100];
char *psrcstr, *pdeststr;
printf("\n Enter source string: ");
gets(srcstr);
printf("\n Enter destination string: ");
gets(deststr);
pdeststr = deststr;
psrcstr = srcstr;
while(*pdeststr++)
;
while(*pdeststr++ = *psrcstr++)
;
printf("%s", deststr);
return 0;
}
For srcstr = " world" and deststr = "hello" I get hello, when I expect to see hello world, which is what I see if I change the first while so
while(*pdeststr);
pdeststr++;
why can't I write all in one line in the first while, just like in the second while?
Your one line loop
while(*pdeststr++);
Is equivalent to
while(*pdeststr)
pdeststr++;
pdeststr++;
Because the postincrement operator is executed before the condition is tested, but after the value for the test is determined.
So you could cater for this with
while(*pdeststr++);
pdeststr--;
Mandatory introduction: do not use gets(), use fgets()!.
Your problem is here:
while(*pdeststr++)
;
The side effect of incrementing is carried out in your last iteration step (when pdeststr points to the NUL terminator), so after this loop, pdeststr points one after your NUL terminator. Write it like this instead:
while(*pdeststr) ++pdeststr;
The boolean value for the while condition is computed before the ++ post-increment.
So when your while loop exits, the post-increment operator is executed one last time, hence pdeststr is pointing right after the null terminator char that follows the word "hello".
Then the rest of the program appends more data after that null char. You end up with the string "hello\0world\0". The print function thinks the string ends at the first null char it encounters.
You have an extra incrementation that point you after the NULL char, and so finally you could print only the first string.
By precedence the postfix increment operator (ptr++) is higher than the indirection (dereference) operator (*ptr). Therefore the
while(*pdeststr++);
will always increment the pdeststr first then evaluate the previously pointed value. As an outcome, when the result of evaluation is 0 the pdeststr actually points to the next element, so there will be a null-terminator character ('\0') between your concatenated words.
As a one-liner solution with while loop you can use the short-circuit evaluation as follows:
while(*pdeststr && pdeststr++);
The code snippet above will stop when *foo results 0 and won't evaluate the foo++ part.
My conclusion is that at the end, deststr = "hello\0 world\0" and because of that printf("%s", deststr); find the first \0 and gives as output hello
"The function returns the character written as an unsigned char cast to an int or EOF on error": see Putchar.
In order to do practice, I produced this program:
#include<stdio.h>
int main(void){
for(putchar('1'); putchar('2'); putchar('3'))
putchar('4');
return 0;
}
It results in an infinite loop whit output ...432432432432432....
I cannot get the reason behind such a result. I expected the loop to print just the same number over and over. I am referring to the value of putchar('4'), where the character '4' should be promoted to the int 52. Why such promotion is not behaving as I expected?
In your case, as per the loop policy,
putchar('1') is executed once.
putchar('2') is evaluated, is found TRUTHY, putchar('4'); is executed, and then putchar('3'); is executed.
back to previous step unless the putchar('2') is FALSY (which never happens).
Hence infinite loop, and every loop iteration includes three putchar statements.
Related to the question "....where the character '4' should be promoted to the int 52" , quoting C11, §7.21.7, (emphasis mine)
The fputc function writes the character specified by c (converted to an unsigned
char) to the output stream pointed to by stream, [...]
and
The putchar function is equivalent to putc with the second argument stdout.
So, it's the character representation which will be printed, and the character representation of '4' is, well, 4.
It does print 124324324324....because putchar(1) is executed at the beginning of the loop and never again.
Putchar prints char on the standard output, and return the same char casted to int. It does not print the char casted to int to the standard output. If you say: putchar('z'), it will print 'z'
putchar(2) at the beginning of each iteration and return the int value of the char '2' which happens to be non zero. This also means that the loop never ends.
putchar('3') is executed at the end of each iteration.
putchar('4') between the beginning and the end of each iteration.
That is why you get that output.
Because putchar ('2') is always != 0 and you execute putchar('4') then action in for which is putchar('3) then condition check putchar('2') which always true and you go to the beginning of this loop