What will be the output of the following C program - c

#include<stdio.h>
int main()
{
char *p;
p="%d\n";
p++;
p++;
printf(p-2, 400);
return 0;
}
When I am running above code, I am getting output 400. But why 400?

The p is assigned the formatting string first. Then it's decrement by 1 two times. Finally its value minus two is passed to the printf with additional parameter 400.
Subtracting 2 from latest value of p moves it back to the original formatting string. And therefore printf prints value 400.

printf()'s first parameter is a format string. The variable p is a pointer to a character array which is also how strings are represented.
When p is assigned a string "%d\n" it says format an integer to print its value and then print the carriage return character.
Since p is a char pointer p++ means move the pointer forward 1 character. This is done twice to move p forward 2 characters so it points to the beginning of the carriage return character. p-2 says do pointer math to give a char* 2 characters in front of where p points.
This is the beginning of the %d carriage return string. This becomes the format string and the second parameter 400 replaces the %d and prints itself followed by the carriage return.

You declared a pointer to a string and assigned it the value "%d\n". This pointer holds an address in memory.
For example, lets say it points to address 6 when you add two to it (which you shouldn't do you you always have to know where your pointers are pointing) you change the address to 8.
Now when you do printf you're replacing it with the current value of the address p points to (8) minus 2 which is 6.

Related

Is this undefined behaviour ( working with string literal)

#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.

Output of the following

Code snippet
int main(){
printf(5 + "GeeksQuiz");
return 0;
}
Output is Quiz
Can you tell me how this output is coming.
Whats the logic behind it.
Addition is commutative. a + b is equal to b + a.
Adding an integer to a pointer increments follows pointer arithmetic. Adding an integer to a pointer increments it by so many elements as the integer count. So (int*)a + b is equal to (int*)((uintptr_t)a + b * sizeof(int))
sizeof(char) is always equal to 1.
"GeeksQuiz" is a string literal. strlen("GeeksQuiz") is equal 9. Accounting for the string terminating null byte, the type of the literal is char[10]. It's an array of 10 characters with the content {'G','e','e','k','s','Q','u','i','z','\0'}.
The C rules say, that an array of type is converted into a pointer to the first element of that array in most contexts. That happens here: (char[])"GeeksQuiz" is converted into a char* pointer to the first character 'G' in the string.
5 + "GeeksQuiz": "GeeksQuiz" is converted to the pointer to the first character. Then that pointer is incremented by 5. So the result of 5 + "GeeksQuiz" will be char* pointer that will point to the character 'Q' inside the string literal.
printf prints the null terminated string passed to it as the first character, except for conversions that start with %, which does not apply here.
To the printf function is passed the address of a pointer that points to the letter 'Q' inside the "GeeksQuiz" string literal.
printf increments the pointer until it will find the string terminating null byte. So it will print {'Q','u','i','z'}, as after z character it will find the null byte.

How to understand the statement of printf(str+9)? [duplicate]

This question already has answers here:
Pointer Arithmetic [closed]
(7 answers)
Closed 5 years ago.
#include<stdio.h>
void main()
{
char *str="CQUESTIONBANK";
clrscr();
printf(str+9);
getch();
}
The output is BANK. what the printf statement does. Can anyone please explain that?
A string in C is defined as a sequence of char terminated by a '\0'. A string isn't a type in C. So, functions handling strings accept a pointer to the beginning of the string (a pointer to char).
You can do arithmetics on pointers. + x means increase the pointer by x elements pointed to. So, str+9 in your example points to the character B. This pointer is passed as the start of the string to printf().
str gives the base address of the pointer to the string.
So normally if you just use printf(str) it should output CQUESTIONBANK.
But in this case you are printing str+9, ie. printf(str+9), so in this case it refers to string starting from the 9th index. In this case the 9th index is B,(C follows 0 indexing), so the string printed is BANK.
printf will always print the string from the passed pointer as starting position till the end of the string, which is stored as '\0' known as Null Character. If you try printf(str[13]), it should print '\0'
#include<stdio.h>
void main()
{
char *str="CQUESTIONBANK";
/* clrscr() function will clear the console.*/
clrscr();
/* printf() function, outputs the data. The name of the string, in your case
it is 'str' always points first element of the string which is 'C'. Adding 9 will
'str' point to 'B' character in the string. That's why printf is printing from B on wards.
Similarly adding 10 to 'str' will print from 'A' and so on.*/
printf(str+9);
/* getch() function waits for you to enter any character.*/
getch();
}
str points to a location (address). You can move in any direction over these addresses using + and -. So, if str points to some address, say 0x1002, then str+1 points to 0x1003 and str-1 points to 0x1001. (assuming str is char*. With other pointer types you move in bigger steps - sizeof(*str))
In your example - str points to an address that holds CQUESTIONBANK so if you move the pointer 9 steps forward, you move past C,Q,U,E,S,T,I,O,N and you now point to BANK. Now using printf will print from that location resulting in BANK

String constant and Character constant

int main(){
printf("the value is %d \n " ,'x'+ "x");
return 0;
}
Output
4196024
But the former one ('x') is an integer and latter one ("x")is a string .
Can I know how ? Or is it giving me a garbage value.
Literal strings have type char [N] where N is just large enough for all characters in the literal plus the terminating '\0' (namely "x" has type char[2]).
In the context of the expression 'x' + "X", the array gets converted to a pointer to its first element, then that address is added with the int value 'x'. The resulting address is passed on to printf() with an invalid conversion specification.
You have invoked Undefined Behaviour!
Try this
printf("the valus is %p\n", (void*)('x' + "x"));
Also note that the address 'x' + "x" is not part of any object in your program. Merely evaluating it is already Undefined Behaviour.
Basically,
printf("the value is %d \n " ,'x'+ "x");
invokes undefined behaviour. What you need is %p format specifier here.
Otherwise, in general,
"string" gives you the base address of the string literal
'p' gives you the ASCII value of the char representation.
So, what essentially is being done here is to print the address of the member in 'x'th element of the string "x" (which does not make much sense, practically).
For better understanding, you can re-write the print statement as
printf("the pointer is %p\n", (void *) ("x"+ 'x'));
which is equivalent to
printf("the pointer is %p\n", (void *) &("x"['x']));
Note that you don't need spaces before or after the newline in the print format.
What you are asking for in the formatted string is an integer so it is printing the integer value of the character 'x' added to the base address of the string literal "x".
'x' is 120 so if you use a memory viewer to peek at the outputted value minus 120 bytes, you will probably find an 'x' followed by a '\0' (= 0).

Storing a format specifier in a pointer

What actually happens when I do this?
{
char * str = "%d\n";
str++;
str++;
printf(str-2,300);
return 0;
}
Intuitively, it appears that the number on the screen will be 300, but I want to know, what gets stored in str.
Edit: It will be great if someone can tell me, when do we actually do this?
Thanks!
str is a memory address, initially the address of the % sign of the string literal %d\n. This literal is created because it is in your code.
Two increments make str point to the character \n and when this is the case, str - 2 is the address of the % sign. So printf sees the format string %d\n, and as usual it prints the first argument after the format string as an integer. The fact is, printf does not care about the origins of the format string. It doesn't matter if you can create it on-the-fly, or hard code it.
We don't do this generally. Sometimes you need to fiddle with a character pointer to scan a string, extract something out of a string, or to skip some prefix of a string.
str is a pointer on the stack. It initially points to (ie, holds the address of) the start of the string literal "%d\n" (this is probably stored in a read-only section of your program by the compiler).
Let's say for example the string literal (the "$d\n") is stored at 0x5000. So (assuming UTF-8 or ASCII) the byte at 0x5000 is %, the byte at 0x5001 is d, 0x5002 is \n (the newline) and at 0x5003 it is \0 (the terminating null character)
str is initially holding the address 0x5000. str++ would increase it to 0x5001, meaning it now points to the string "d\n", ie one character into the string literal "%d\n". Likewise, str++ again moves it to 0x5002, ie the string "\n", two characters into the string literal "%d\n". Note that all of these are still terminated by the null character at 0x5003 (how C knows when the string ends).
The printf call has the format string as the first argument. str at this point holds 0x5002, so the call is saying 'Use the format string starting at 0x5002 - 2 = 0x5000', which turns out to be the same string that we started with.
Thus it will be the same as calling
printf("%d\n",300)
and will print out 300.
Well you are declaring a char pointer. This pointer will hold a RAM address from where you will write the following bytes: % (1 byte) d (1 byte) \n (1byte on UNIX, 2 bytes on windows) and \0 the null terminating byte that ends your string.
Then you increment by two your pointer value (which is the address of the first byte) then decrement by two. So basically you do nothing. Thus when calling printf() src-2 will point to %d\n and the null terminating byte will make it exactly pass %d\n.
So at the end of the day what you are doing is:
printf("%d\n", 300); Hence the 300 output.

Resources