I executed this code after compiling in codeblocks:-
#include <stdio.h>
int main()
{
char arr[]="HELLO";
int a=arr;
return printf("...%s ,%s\n",arr,&a+1);
}
I got this output:-
...HELLO,HELLO
when I changed &a to a,printf returned -1.
I am not able to sort out this address logic ,please help.
(A friend gave me this code and asked its explanation, and I am not able to find it). So I would like to know why..
Thanks
You are telling printf to expect a string, but you are giving it the address of an int (&a). This invokes undefined behaviour, so anything could happen.
[In practice, what's probably happening is that the compiler places a directly below arr on the stack. So &a+1 ends up equal in value to &arr. printf then reinterprets that address as a pointer-to-char, and so ends up printing HELLO. If the compiler happened to arrange the stack differently, you'd observe different behaviour.]
Related
I had gone to an interview in which I was asked the question:
What do you think about the following?
int i;
scanf ("%d", i);
printf ("i: %d\n", i);
I responded:
The program will compile successfully.
It will print the number incorrectly but it will run till the end
without crashing
The response that I made was wrong. I was overwhelmed.
After that they dismissed me:
The program would crash in some cases and lead to an core dump.
I could not understand why the program would crash? Could anyone explain me the reason? Any help appreciated.
When a variable is defined, the compiler allocates memory for that variable.
int i; // The compiler will allocate sizeof(int) bytes for i
i defined above is not initialized and have indeterminate value.
To write data to that memory location allocated for i, you need to specify the address of the variable. The statement
scanf("%d", &i);
will write an int data by the user to the memory location allocated for i.
If & is not placed before i, then scanf will try to write the input data to the memory location i instead of &i. Since i contains indeterminate value, there are some possibilities that it may contain a value equivalent to the value of a memory address or it may contain a value which is out of range of memory address.
In either case, the program may behave erratically and will lead to undefined behavior. In that case anything could happen.
Beacuse it invokes undefined behavior. The scanf() family of functions expect a pointer to an integer when the "%d" specifier is found. You are passing an integer which can be interpreted as the address of some integer but it's not. This doesn't have a defined behavior in the standard. It will compile indeed (will issue some warning however) but it will certainly work in an unexpected way.
In the code as is, there is yet another problem. The i variable is never initialized so it will have an indeterminate value, yet another reason for Undefined Behavior.
Note that the standard doesn't say anything about what happens when you pass a given type when some other type was expected, it's simply undefined behavior no matter what types you swap. But this particular situation falls under a special consideration because pointers can be converted to integers, though the behavior is only defined if you convert back to a pointer and if the integer type is capable of storing the value correctly. This is why it compiles, but it surely does not work correctly.
You passed data having the wrong type (int* is expected, but int is passed) to scanf(). This will lead to undefined behavior.
Anything can happen for undefined behavior. The program may crash and may not crash.
In a typical environment, I guess the program will crash when some "address" which points to a location which isn't allowed to write into by the operating system is passed to scanf(), and writing to there will have the OS terminate the application program, and it will be observed as a crash.
One thing that the other answers haven't mentioned yet is that on some platforms, sizeof (int) != sizeof (int*). If the arguments are passed in a certain way*, scanf could gobble up part of another variable, or of the return address. Changing the return address could very well lead to a security vulnerability.
* I'm no assembly language expert, so take this with a grain of salt.
I could not understand why the program would crash? Could anyone explain me the reason. Any help appreciated.
Maybe a little more applied:
int i = 123;
scanf ("%d", &i);
With the first command you allocate memory for one integer value and write 123 in this memory block. For this example let's say this memory block has the address 0x0000ffff. With the second command you read your input and scanf writes the input to memory block 0x0000ffff - because you are not accessing (dereferencing) the value of this variable i but it's address.
If you use the command scanf ("%d", i); instead you are writing the input to the memory address 123 (because that's the value stored inside this variable). Obviously that can go terribly wrong and cause a crash.
Since there is no &(ampersand) in scanf(as required by the standard), so as soon as we enter the value the program will terminate abruptly, no matter how many lines of code are written further in the program.
-->> I executed and found that in code blocks.
Same program if we run in turbo c compiler then it will run perfectly all the lines even which are after scanf, but the only thing, as we know the value of i printed would be garbage.
Conclusion:- Since at some compiler it will run and at some it would not, so this is not a valid program.
In C, inside a function, if we declare a variable and don't initialise it, it generates a garbage value and stores it in the variable.
Whereas in Java, it does not allow you to use a local variable without initialising in a method.
But the code below, when compiled and ran on online C compilers,
Idk why instead of generating garbage values, it is printing "123". (without quotes)
#include <stdio.h>
void f();
int main(){
f();
f();
f();
}
void f(){
int i;
++i;
printf("%d", i);
}
"I do not know why instead of generating garbage values, it is printing "123"."
When any expression in the program invokes Undefined Behavior, which is made by
incrementing and printing the indeterminate value of i, the result/output does not need to be wrong, but there will never be a guarantee that it will be correct, which is a reason to never rely on any of such a code, does not matter if it prints the right values in one specific case.
Thus, you do not need to smash your head around finding a reason for that behavior.
Because of common implementations of C, an uninitialized value near the start of a C program is likely to be 0, so your subsequent ++i operations change it to 1 2 and 3.
However, take good note of this:
Just because it is likely to be zero does not guarantee it will be zero.
This is undefined behavior, and the values could correctly come out to be anything.
I had gone to an interview in which I was asked the question:
What do you think about the following?
int i;
scanf ("%d", i);
printf ("i: %d\n", i);
I responded:
The program will compile successfully.
It will print the number incorrectly but it will run till the end
without crashing
The response that I made was wrong. I was overwhelmed.
After that they dismissed me:
The program would crash in some cases and lead to an core dump.
I could not understand why the program would crash? Could anyone explain me the reason? Any help appreciated.
When a variable is defined, the compiler allocates memory for that variable.
int i; // The compiler will allocate sizeof(int) bytes for i
i defined above is not initialized and have indeterminate value.
To write data to that memory location allocated for i, you need to specify the address of the variable. The statement
scanf("%d", &i);
will write an int data by the user to the memory location allocated for i.
If & is not placed before i, then scanf will try to write the input data to the memory location i instead of &i. Since i contains indeterminate value, there are some possibilities that it may contain a value equivalent to the value of a memory address or it may contain a value which is out of range of memory address.
In either case, the program may behave erratically and will lead to undefined behavior. In that case anything could happen.
Beacuse it invokes undefined behavior. The scanf() family of functions expect a pointer to an integer when the "%d" specifier is found. You are passing an integer which can be interpreted as the address of some integer but it's not. This doesn't have a defined behavior in the standard. It will compile indeed (will issue some warning however) but it will certainly work in an unexpected way.
In the code as is, there is yet another problem. The i variable is never initialized so it will have an indeterminate value, yet another reason for Undefined Behavior.
Note that the standard doesn't say anything about what happens when you pass a given type when some other type was expected, it's simply undefined behavior no matter what types you swap. But this particular situation falls under a special consideration because pointers can be converted to integers, though the behavior is only defined if you convert back to a pointer and if the integer type is capable of storing the value correctly. This is why it compiles, but it surely does not work correctly.
You passed data having the wrong type (int* is expected, but int is passed) to scanf(). This will lead to undefined behavior.
Anything can happen for undefined behavior. The program may crash and may not crash.
In a typical environment, I guess the program will crash when some "address" which points to a location which isn't allowed to write into by the operating system is passed to scanf(), and writing to there will have the OS terminate the application program, and it will be observed as a crash.
One thing that the other answers haven't mentioned yet is that on some platforms, sizeof (int) != sizeof (int*). If the arguments are passed in a certain way*, scanf could gobble up part of another variable, or of the return address. Changing the return address could very well lead to a security vulnerability.
* I'm no assembly language expert, so take this with a grain of salt.
I could not understand why the program would crash? Could anyone explain me the reason. Any help appreciated.
Maybe a little more applied:
int i = 123;
scanf ("%d", &i);
With the first command you allocate memory for one integer value and write 123 in this memory block. For this example let's say this memory block has the address 0x0000ffff. With the second command you read your input and scanf writes the input to memory block 0x0000ffff - because you are not accessing (dereferencing) the value of this variable i but it's address.
If you use the command scanf ("%d", i); instead you are writing the input to the memory address 123 (because that's the value stored inside this variable). Obviously that can go terribly wrong and cause a crash.
Since there is no &(ampersand) in scanf(as required by the standard), so as soon as we enter the value the program will terminate abruptly, no matter how many lines of code are written further in the program.
-->> I executed and found that in code blocks.
Same program if we run in turbo c compiler then it will run perfectly all the lines even which are after scanf, but the only thing, as we know the value of i printed would be garbage.
Conclusion:- Since at some compiler it will run and at some it would not, so this is not a valid program.
While writing the following code I should get an error. The array size is given as zero(which I suppose is illegal) and furthermore sprintf is printing "abc" to a which has not been allocated any memory but I am getting the output as "abc". I cant understand why?
#include<stdio.h>
#include<string.h>
int main()
{
char a[0];
sprintf(a,"%s","abc");
printf("%s\n",a);
return 0;
}
I am getting the correct output when i am giving the array size to be 1,2,3 which should not be the case while it is giving segmentation fault for explicitly using a as a pointer ,i.e, using char *a(which is expected). Can somebody explain the internal working?
No, there's no reasonable explanation. By using an array which is smaller than the string to be printed, your program invokes undefined behavior. That means that literally anything can happen, including the fact that everything seems to be working fine. Undefined behavior doesn't mean that the program must crash, it means that it can crash.
int main()
{
int i,j,k;
i=1;j=2;k=3;
int *p =&k;
*(p-1)=0;
printf("%d%d%d",i,j,k);
getch();
}
the output is 1 2 3.
Your program exhibits undefined behavior, the pointer arithmetics you're doing is invalid.
You can only do pointer arithmetics on pointers that actually point into an array, and the result of the addition or subtraction must still point inside the array (or one past its end, if you don't intend to dereference it).
So anything could happen, the compiler can generate whatever code it feels like for that code.
You are not allowed to refer to p-1 after assigning it &k this is an invalid pointer for you, and the behavior of using it is undefined.
A run-time error only occurs if your stray pointer hits something that raises that error, such as some protected memory or a location that will later become a divisor in some calculation (0), for example.