Reputation: 385
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.
Upvotes: 0
Views: 175
Reputation: 21
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.
Upvotes: 0
Reputation: 70412
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.
Upvotes: 0
Reputation: 319
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!
Upvotes: 0
Reputation: 58271
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.
Upvotes: 1
Reputation: 6606
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.
Upvotes: 0
Reputation: 2179
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.
Upvotes: 0
Reputation: 61910
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.
Upvotes: 0
Reputation: 3097
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
.
Upvotes: 0
Reputation: 283684
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.
Upvotes: 4