Reason for the Output - c

#include<stdio.h>
int main(void)
{
int a=5;
printf("%d"+1,a);
}
Output: d.
I didn't get how the output is coming: d ?

You passed as first argument of printf "%d"+1; "%d" is actually seen as a const char * that points to a memory location where %d is stored. As with any pointer, if you increment it by one, the result will point to the following element, which, in this case, will be d.
a is not used, but this should not be a problem since in general (I don't know if it's standard-mandated Edit: yes it is, see bottom) the stack cleanup responsibility for variadic functions is up to the caller (at least, cdecl does it that way, this however may or may not be UB, I don't know*).
You can see it easier this way:
#include<stdio.h>
int main(void)
{
int a=5;
const char * str="%d";
printf(str + 1, a);
}
str ---------+
|
V
+----+----+----+
| % | d | \0 |
+----+----+----+
str + 1 ----------+
|
V
+----+----+----+
| % | d | \0 |
+----+----+----+
Thus, ("%d"+1) (which is "d") is interpreted as the format string, and printf, not finding any %, will simply print it as it is. If you wanted instead to print the value of a plus 1, you should have done
printf("%d", a+1);
Edit:
* ok, it's not UB, at least for the C99 standard (§7.19.6.1.2) it's ok to have unused parameters in fprintf:
If the format is exhausted while arguments remain, the excess arguments are
evaluated (as always) but are otherwise ignored.
and printf is defined to have the same behavior at §7.19.6.3.2
The printf function is equivalent to fprintf with the argument stdout interposed
before the arguments to printf.

String literals are pointers. Advancing the pointer to "%d" by 1 results in "d". The argument is discarded.

You should do printf("%d", a+1). "%d" + 1 is a pointer to "d" inside an array of char ({'%','d','\0'}).

Because of +1. If you want to increment a do: printf("%d", a + 1); instead.

Suppose you had:
char x[] = "%d";
What do you expect
printf(x + 1, a);
to print?
Hint: t.c:5: warning: too many arguments for format

"%d" is String constant, it will be stored in the char[] in the memory. During runtime, "%d" returns the starting location of the char[]. Increasing character array pointer by one, will point to the next character. Hence "d" alone is passed to the printf function. so the output is "d"

Related

Adding an integer to C-String while printing

int main(){
printf("hello world"+2);
}
test.c:32:25: warning: adding 'int' to a string does not append to the string
[-Wstring-plus-int]
printf("hello world"+2);
~~~~~~~~~~~~~^~
test.c:32:25: note: use array indexing to silence this warning
printf("hello world"+2);
^
& [ ]
1 warning generated.
alpha#Desktop % ./a.out
llo world%
So this is what I am getting. And if I increase the number then it is simply slicing the string by that.Can anyone explain this output and why it's happening to me?
In the C and C++ languages, every string that has been defined with double quotes is of type char* (pointer to char) as a statically allocated char array. When you call printf() on such string it does something like this:
void printf(char* str) {
while(*str!= '\0') {
// write the current character to stdout
write(STDOUT_FILENO, str, sizeof(char));
str ++;
}
}
I don't know if it really is written that way, indeed it probably isn't, the functionality is the same. It iterates over the string until it finds the null-terminator ('\0'). All pointers are almost equivalent to long and when you add a number to them, it increments their underlying value with sizeof(type), where type is the type of value the pointer points towards. Thus, when you add a number to "Hello World", makes printf() think your string starts on a different memory address and prints 'llo World'.
If you want to print the string with the value '2' appended to the end of it, as #Elliott Frisch stated, you would use print("Hello World%d", 2).
I would suggest looking at sprintf() and strcat() for string concatenation in C.
In C, what we might think of as a string is actually an array of characters. What you pass to printf() in both cases is a pointer to the start of such an array. You can do arithmetic with pointers, which is what you are doing here.
Here's some clarification.
#include <stdio.h>
int main(void) {
// A
printf("Hello, world!\n");
// B
printf("Hello, world!\n" + 2);
}
Output:
Hello, world!
llo, world!
In case A, you point to the start of an array containing the H character, and it reads until the last one (which is in fact a 'this is the end'-character: \0).
⬇️
H
e
l
l
o
,
w
o
r
l
d
!
\n
\0
In case B, you add 2 to the pointer before passing it to printf(). Now printf() starts reading here:
⬇️
H
e
l
l
o
,
w
o
r
l
d
!
\n
\0
This is what causes your 'slice'.

Can anyone tell me how this piece of code works?

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void print_reverse(char *s)
{
size_t len=strlen(s);
char *t=s+len-1;
printf("%s %s\n",t,s);
while(t>=s){
printf("%c",*t);
t=t-1;
}
puts("");
}
int main(){
print_reverse("Hello");
}
Can anyone tell how char *t=s+len-1; and while(t>=s) works. I cant understand how a number can be added to pointer and how the pointers are compared in while loop. This program is for reversing a string in c.
Lets do this line by line:
print_reverse("Hello");
void print_reverse(char *s)
Now s points to a string that contains:
- - ----+----+----+----+----+----+----+---- - -
| H | e | l | l | o | \0 |
- - ----+----+----+----+----+----+----+---- - -
^
s
That last character is called the string "NUL" terminator because "NUL" is the name of the character with ASCII value zero (all ASCII values that are not printable have three letter names).
size_t len=strlen(s);
Now len has a value of five. Notice it does not include the "NUL" terminator so even though the string takes 6 bytes the length is five.
char *t=s+len-1;
Now t has a value of s+4. If you count the memory locations this is what you get:
- - ----+----+----+----+----+----+----+---- - -
| H | e | l | l | o | \0 |
- - ----+----+----+----+----+----+----+---- - -
^ ^
s t
Note that s+strlen(s) would point to the "NUL" terminator.
printf("%s %s\n",t,s);
That printf should print Hello o
while(t>=s)
This while loop will continue as long as t>=s which means it will do the body of the loop for every character, including the one where s is pointing.
printf("%c",*t);
This prints the contents of the memory that t is pointing at. It starts with the o and continues backwards towards the H.
t=t-1;
That the part that moves t backwards. Eventually t will be past s and then the loop will end. When the loop finishes it will look like this:
- - ----+----+----+----+----+----+----+---- - -
| H | e | l | l | o | \0 |
- - ----+----+----+----+----+----+----+---- - -
^ ^
t s
Then there is this one final line:
puts("");
That prints an empty string and a final linefeed - there wasn't a linefeed in the string but we needed one so this is a way to do that.
Pointer Arithmetic
When a pointer points into an array, adding integers to the pointer or subtracting integers from the pointer moves the pointer back and forth within the array.
This function should be passed a char *s that points to a string, which is an array of characters ending in a null character ('\0'). Then size_t len = strlen(s); sets len to the size of this string, and char *t = s+len-1; sets t to point to the last character before the null character.
Then, in the loop t=t-1; moves t backward.
Unfortunately, this loop uses t>=s as its control condition. This is intended to stop when t has been moved to the character before s, meaning it has gone back before the start point. However, the C standard only defines pointer arithmetic for elements within the array plus a special position at the end of the array. If this function is passed an s that points to the beginning of an array, then the loop will eventually make t point before the array, and the C standard does not define the resulting behavior.
Other Things to Know About Pointer Arithmetic
Any object may be treated as an array of one element. If you have some type T and some object T x;, you may set a pointer T *p = &x;, and then it is allowed to advance the pointer by one element, p = p+1;. Dereferencing that pointer with *p is not defined, but you can compare it, as in &x == p, or you can subtract one from it.
If print_reverse were passed a pointer into an array beyond the beginning, then its loop would be okay. However, that is now how it is used in the example code; print_reverse("Hello"); is not good code.
Any object may be treated as an array of characters. You can convert a pointer to any object to a pointer to unsigned char and then examine the bytes that make up an object. This is used for special purposes. You should not use it in general code while you are learning C, but you should be aware it exists.

Unable to understand the output of the program using printf weirdly

I was working with some of the interview questions when I found this code.
#include<stdio.h>
int main()
{
short int a=5;
printf("%d"+1,a); //does not give compiler error
return 0;
}
It prints the following:
d
I am unable to understand how the printf function works here.
Let's look at the first argument to the printf() call.
"%d" + 1
This points to the same thing as ptr does in the following code.
char *ptr = "%d";
ptr = ptr + 1;
So, what does it mean to increment a pointer? Well, we advance the pointer sizeof(*ptr) * 1 bytes forward.
So, in memory we have:
%d\0
^^
||
|This is where ("%d" + 1) points to.
This is where ("%d") points to.
So, your code is more or less functionally equivalent to doing:
short int a = 5;
printf("d", a);
Which will evaluate and then ignore the extra function argument and print d.
One more thing: You're very close to causing undefined behavior in that code. printf("%d", a) is using the wrong format string. The correct format string for a short int is "%hd".
You can find a full table of format strings here.
"%d" + 1 does pointer arithmetic, the compiler sees it as "d", so
printf("%d"+1,a);
becomes:
printf("d", a);
You can see why it outputs d in your compiler.
As #sharth points out in the comment, the extra argument a here is evaluated and discarded.
This is my answer based off #DCoder 's comment. "%d" is a pointer to the first character of the two character array %d. Incrementing this by one gives a pointer to d. The fact that there is a second argument now does not matter as the result of the expression "%d"+1 is simply the character d. If you try adding 0 your output is 5 as expected. If you try adding 2, there is no output as there is only "" is being passed to printf.
In this case printf("%d"+1,a); = printf("d",a).
You are specifying printf to print from +1 position which is "d", so printf will simply print d on screen.

couldn't able to access the first subscript of an array when %s is used but possible with %c

#include <stdio.h>
#include <string.h>
void main()
{
char array[]="hello";
printf("%s",array[0]);
printf("%c",array[0]);
}
couldn't able to access array[0] when %s is used but able to access array[0] when %c is used, help me to find a solution for this.
you should use address while using with %s ==> &array[0]
because %s requires a pointer as argument.
usually we use
printf("%s",character_array_name);
here character_array_name is the address of first element
character_array_name == &character_array_name[0];
and if you want to print only one character , you need to use
printf("%.1s",character_array_name);
Example Code:
#include<stdio.h>
int main()
{
char *str="Hello World";
printf("%s\n",str); //this prints entire string and will not modify the pointer location but prints till the occurence of Null.
printf("%.1s\n",str); //only one character will be printed
printf("%.2s\n",str); //only two characters will be printed
//initially str points to H in the "Hello World" string, now if you increment str location
str++; //try this str=str+3;
printf("%.1s\n",str); //only one character
printf("%.2s\n",str); //only two characters will be printed
str=str+5; //prints from the W
printf("%s\n",str); //this prints upto Hello because scanf treats space or null as end of strings
printf("%.1s\n",str); //only one character
printf("%.2s\n",str); //only two characters will be printed
return 0;
}
Although you have accepted an answer , I thought my answer could help you in a certain way.
String literals are a sequence of characters and you can visualize your array like this :
+---+---+---+---+---+----+
array: | h | e | l | l | o | \0 |
+---+---+---+---+---+---+-
^
|
array[0]
printf is a variadic function and it doesn't know anything about its arguments until you specify them , so when it sees %c format specifier it assumes that the next argument will be a variable storing a character ,in this case its array[0] that is the character h is stored at the index 0 of the array .
Now, when printf sees a %s it assumes that the next argument will be a pointer pointing the string literal ("hello") that you want it to print , in this case array[0] is not a pointer, you should put array instead in the printf , please note that array names are not pointers but array name decays to pointer
Besides , you should use int main(void) in place of void main its standard

Can not explain output of simple string operation in C

This is the code:
#include<stdio.h>
#include<string.h>
int main()
{
char *s = "name";
int n = strlen(s);
int i;
s = &s[n+1];
for(i=0; i<=n; i++)
{
printf("%d %c",i,*s);
s++;
}
return 0;
}
Output:
0 %1 d2 3 %4 c
I am unable to understand the output. Why its printing % although there's no escape sequence.
This line s = &s[n+1]; is causing your pointer to point off into the middle of nowhere. After that you start reading random garbage from it. Apparently that random garbage includes some % characters.
First assign s = &s[n+1]; then access out of bound memory in printf using *s. code is runing under Undefined behavior according to C standards.
Maximum index to s[] can be length of string that contains \0. Remember index value start from 0 to size of (array/string)-1
Your string is stored in memory something like:
s 23 24 25 26 27 28
+----+ +----+----+----+----+----+----+
| 23 | | n | a | m | e | \0 | ? |
+----+ +----+----+----+----+----+----+
0 1 2 3 4 5
s points to string "name"
string length of "name" is 4
length("name") + 1 = 5
? means garbage values
In expression s = &s[n+1];, n + 1 is five 5 that pointing to a location outside allocated memory for "name" string And in printf statement you access memory using * Dereference operator cause invalid memory access and behavior of this code at run time is Undefined. That is the reason you code behaving differently at different execution.
Your code compiles correctly because syntactically it correct, But at runtime access of unallocated memory can be detected by OS kernel. This may causes OS kernel send a signal core dump to the your process which caused the exception. (interesting to note: as OS detects memory right violation by a process -- An invalid access to valid memory gives: SIGSEGV And access to an invalid address gives: SIGBUS). In worth case your program may execute without any failure it produces garbage results.
s = &s[n+1];
Makes s to point unknown memory. Referring s thereafter invokes undefined behavior and anything may happen when you access it in printf.
Undefined behaviour because whenever you do s[n+1] where n is the length of the string. Also you are assigning this new address into s again. Accessing every index starting from this location will result in undifined behaviour, because you have no idea what lies at those locations, and you have access to it or not.
You may try defining another string immediately after the one you defined.
char *s = "name";
char *d = "hello test";
In that case you might end up printing the characters from the string "hello test", if the compiler happens to store the string immediately after the string "name" in the read only area. This is not guranteed.
The bottom line is that, the piece of code is not correct and results in undefined behaviour.
You are changing the pointer of s to the end of your screen, that's why you have some random garbage.
If for exemple you change your main to
void foo(char *str)
{}
int main()
{
char *s = "name";
int n = strlen(s);
int i;
s = &s[n+1];
foo("Test");
for(i=0; i<=n; i++)
{
printf("%d %c\n",i,*s);
s++;
}
return 0;
}
I think it will display test
But you should not do such thing.
s = &s[n+1]; is assignment from out of bound. value of s[n] is '\0' and after this which is s[n+1] will have some garbage value.
Assignment shown above is assigning base address of s[n+1] to s and later you are trying to print values from this new s so all values will be garbage.Accessing out of bound is Undefined behaviour.
in your program:
n = 4;
s = &s[n + 1] = &s[5];
pointer s points to a memory not uninitialized, so the output should be uncertain!
You asked:
Why its printing % although there's no escape sequence.
The escape sequence to print a % only applies when you are trying to print the % from within the format string itself. That is:
printf("%% %d\n", 1);
/* output:
% 1
*/
There is no need to escape it when it is being provided as the argument for the format conversion:
printf("%s %c\n", "%d", '%');
/* output:
%d %
*/
Your program invokes undefined behavior, since you are making s point one past the last valid object to which it is pointing to (which is allowed), and then you are reading from it (and beyond) during the printing loop (which is not allowed). Since it is undefined behavior, it could do nothing, it could crash, or it could create the output you are seeing.
The output you are getting can be obtained from the following program:
#include <stdio.h>
int main () {
const char *s = "%d %c";
int i;
for (i = 0; i < 5; ++i) {
printf("%d %c", i, *s);
s++;
}
puts("");
return 0;
}
/* output is:
0 %1 d2 3 %4 c
*/
This output would be less strange if there was a delimiter between each call to printf. If we add a newline at the end of the output after each call to printf, the output becomes:
0 %
1 d
2
3 %
4 c
As you can see, it is simply outputting the string pointed to by s, where each character it prints is preceded by the index position of that character.
As many people have pointed out, you have moved the pointer s past the end of the static string.
As the printf format string is also a static string there is a chance that the memory next to the static string "name" is the printf format string. This however is not guaranteed, you could just as well be print garbage memory.

Resources