Need to understand behaviors of printf - c

1)
char* fun()
{
return "awake";
}
int main()
{
printf("%s",fun()+ printf("I see you"));
return 0;
}
output :: I see youee you
int main()
{
printf("%s",5+printf("I see you"));
return 0;
}
output :: Runtime crashing
1) Why both scenario as different behaviour?
2) can anyone explain why "awake" is not printed in first PRINTF?
3) is scenario 1 is depend on the compiler?

This
printf("%s",fun()+ printf("I see you"));
adds the result of fun() (the address of your "awake" string literal) to the result of calling printf(), which is the integer value 9, the number of characters printed. That is a character address plus an integer offset - perfectly legal - and it just happens to be several characters into the "I see you" string literal, so it then prints out the end of the `"I see you" string.
This
printf("%s",5+printf("I see you"));
tries to print as a NUL-terminated string whatever is at the at the virtual memory address 14, which probably isn't even mapped into the process address space.

Related

String terminator issues

If I type in this code, it compiles and runs (I use GCC)
#include<stdio.h>
int main()
{
char sentence[8]="September";
printf("The size of the array is %d \n",sizeof(sentence));
printf("The array is %s \n",sentence);
}
and gives the output
The size of the array is 8
The array is Septembe
How is this working? A string terminator is needed for C to know that the string has ended. How is the array worth 8 bytes of space and knows where to stop?
By passing a non-NUL-terminated string to printf("%s"), you're invoking undefined behavior.
By its very nature, the result is undefined. It may seemingly "work" (like you're seeing).
As others have explained, what's probably happening is that there happens to be a zero byte after your string, which stops printf from going further. However, if you were to add more stuff around that variable, you'd probably see different behavior:
#include<stdio.h>
int main(void)
{
char sentence[8] = "September"; // NOT NUL TERMINATED!
char stuff[] = "This way is better";
printf("%s\n", sentence); // Will overrun sentence
return 0;
}

How printf statement works in the below code?

void main()
{
printf("Adi%d"+2,3);
}
output= i3
This printf statement worked, but how the statement worked ?
printf("Adi%d"+2,3);
"Adi%d" - is interpreted as start of the address of the memory where the string literal "Adi%d" is stored. When you add 2 to it, it became address of memory where string "i%d" is stored. So basically you passed to printf string: "i%d". Then %d and printf came into play replacing %d with 3, hence the output i3.
Its part of pointer to character, nothing to do with printf, "Adi" + 2 will make it read from position 0 + 2 = 2 that will be i
int main()
{
char* a = "Adi" + 2;
printf(a); // output i
}

while() loop keeps iterating unexpectedly

program
int main()
{
int a=0xabcd;
char *p=&a;
while(p)
{
if(*p=='c')
{
printf("i got %c\n",*p);
return;
}
p++;
}
}
1)why i got always an answer like "i got c".
2)no matter how many times i execute this program, why i got %c as c.
3)replace c character with any character, no matter ,why we got such a character that what we put in if condition?.
if(*p=='z') or if(*p=='t') or ....
4)can anybody explain what was the reason?
int a=0xabcd on a 32 bit machine will give you 0x0000abcd. If you try to read the contents of this integer as a character, you'll either get 0x00 or 0xcd, depending on endianess. Neither is a printable ASCII character. This doesn't make any sense.
while(p) means "while p points at an address which is not zero". This doesn't make any sense. Because of this, you continue to loop and read random memory cells outside the allocated integer. Anything can happen. If you are lucky, the program will crash.
To sum it up, it appears you don't quite know what you are doing...
1) You get i got c because your program has a pointer p that points on each bytes of 0xabcd in sequence and beyond ! At some point, the pointer will point on the byte 0x63 which is 'c'. Since this is the if condition, the print statement prints the char pointed by p and you see the message i got c.
2) because of the if condition that execute the print statement only if the byte pointed by p is 0x63 thus 'c'. This is why you always see the same message. Note however that it only works if there is a byte with value 0x63 somewhere in memory.
3) You would write it like this to display other characters.
if((*p=='z') || (*p=='t') || ....)
4) see above answers.
Apart from the nice answer by Mr. #Lundin, just to clarify the logic for the print s,
1)why i got always an answer like "i got c".
Because, you wrote the code to do so. Keeping away the programmatic errors, if you check the logic, you wrote the code so that the printf() will only be executed if *p has a value equal to c. So, no wonder, all the time printf() (if encountered) will print
i got c
Next,
2) no matter how many times i execute this program, why i got %c as c.
Correct. Same reason as above.
3)replace c character with any character, no matter ,why we got such a character that what we put in if condition?.
Your printf() will only be executed if the if condition satisfies. So whatever character you'll use in your if condition, printf() will print only that character only.
You don't seem to know what you're doing.
Closest working exaple would look like this:
#include <stdio.h>
int main()
{
int a[2] = {0x0a0b0c0d, 0};
char *p = (char *) a;
while (*p)
{
if (*p == 0x0c)
{
printf("i got c\n");
return 0;
}
p++;
}
}
Or another better solution:
#include <stdio.h>
int main()
{
int a = 0x0a0b0c0d;
for (int i = 0; i < sizeof (int); i++)
{
if(((char *) &a)[i] == 0x0c)
{
printf("i got c\n");
return 0;
}
}
}

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.

Strange characters in c

This is my source code:
#include <stdio.h>
#include <string.h>
void main()
{
int broj_znakova,i=0;
char niz1[81],niz2[81];
printf("Enter something, for end Ctrl/c \n\n");
while(fgets(niz1,81,stdin)!=NULL)
{
continue;
}
printf("You just enter: %s \n",niz1);
printf("This string is long %d\n",(strlen(niz1)-1));
strcpy(niz1,niz2);
printf("niz2 is %s\n",niz2);
if(strcmp(niz1,niz2)==0)
{
printf("niz1 and niz2 is same\n");
}
else
{
printf("niz1 != niz2\n");
}
while(niz1[i]!='\n')
{
if(niz1[i]==' ')
{
broj_znakova ++;
i=i+1;
}
}
printf("Spaces in string = %d\n",broj_znakova);
}
When i press Ctrl/c i got a bunch of strange characters, can someone help???
I google something about flushing but i'm new :)
The contents of niz2 is not initialized. It will result in undefined behavior. Perhaps you meant to copy niz1 to niz2. If so, then you need to reverse the parameters in the strcpy call. With strcpy, the first parameter is the target.
Note too that the variable broj_znakova is never initialized.
C does not "zero out" information in memory (in general) so when it allocates variables, you get whatever is there in memory at the time (whether it is logically readable as words or not), if you are printing something without the system knowing this is a string then it will keep printing until it encounters a NULL terminating character, if there is none, it tries to print whatever is in memory and this produces the weird characters.
On this line
strcpy(niz1,niz2);
I believe your parameters are reverse, it should be strcpy(niz2, niz1); The strange characters you are seeing is because niz2[81] has memory allocated, but it's not "filled in". So you get whatever 'magical' data that allocation may contain. That is, until you put something in it, or do memset, etc.

Resources