I was solving C programming Questions and I came across this
#include<stdio.h>
int main()
{
int x=100,y=200,z=300;
printf("%d..%d..%d");
}
I expected an error but the output was 300..200..100
Can anyone explain this output?
%d in printf expects int type argument. You are passing no arguments. Its a constraint violation and ultimately your program invokes undefined behavior.
your code has so many warning says..
root#jeegar:~/test# gcc -Wall testprintf.c
testprintf.c: In function ‘main’:
testprintf.c:5:4: warning: too few arguments for format
testprintf.c:4:20: warning: unused variable ‘z’
testprintf.c:4:14: warning: unused variable ‘y’
testprintf.c:4:8: warning: unused variable ‘x’
testprintf.c:6:1: warning: control reaches end of non-void function
when i run your code it shows different result each time.
root#jeegar:~/test# ./a.out
1822880072..1822880088..4195632root#jeegar:~/test#
root#jeegar:~/test#
root#jeegar:~/test# ./a.out
-1388515512..-1388515496..4195632root#jeegar:~/test#
root#jeegar:~/test#
root#jeegar:~/test#
root#jeegar:~/test# ./a.out
401499528..401499544..4195632root#jeegar:~/test#
So here it's undefined behavior
It may be posible that undefined behavior result same value as yours
printf is
int printf(const char*, ...)
a function with variable number of arguments. printf identify number of arguments using const char string - it count number of % signs. It takes first argument after const char argument and walks down the stack. It occasionally happened that local variables are situated just under function frame. But on other compilers and with other directives you will get other results, because in this case behaviour is undefined. For example, on my computer I get 0, 100, 200. On win VSE I get 0..0..random number in debug mode and rand.. 0 .. rand in release mode, etc.
When you use "%d" you are saying that a integer input should go there, but you never supply the integer to use. You need to add the integers as arguments after the string, like this:
#include<stdio.h>
int main()
{
int x=100,y=200,z=300;
printf("%d..%d..%d", x, y, z);
}
If you run printf("%d..%d..%d"); you will still get an output, but it will be some random un-initialized values.
Related
I was randomly experimenting with code and tried to assign printf to an integer variable, using different compilers. Different values were returned. What is the explanation for that?
#include <stdio.h>
int main ()
{
int x;
x = printf;
printf ("%d", x);
return 0;
}
Value returned on my compiler is 4195360.
Look at the warnings from your compiler. (If your compiler doesn't show a warning for this code, look up how to configure it to show useful warnings.)
a.c:5:5: warning: incompatible pointer to integer conversion assigning to 'int'
from 'int (const char *, ...)' [-Wint-conversion]
x = printf;
^ ~~~~~~
1 warning generated.
printf is a function. Every function can be used as a pointer to that function. A pointer to a function is a way to refer to the function that can be placed into a variable. Typically, it's the address of the code of the function in memory.
It's possible to assign a pointer to an integer. The resulting value depends on your system. The integer is typically the address of the code of the function in memory.
There's nothing useful you can do with this value except in some very particular circumstances (such as crafting binary exploits, or managing dynamic code loading). Anything you can do with the value would be very specific to a particular hardware and software environment.
In C, when & is absent for an argument in scanf(), no compilation error is produced; instead, the displayed results are wrong (i.e. a semantic error occurs).
Consider the following code:
char str[30];
int a;
printf("Enter the value");
scanf("%s %d", str, a); // This is the statement in question.
printf("You entered %s %d", str, a);
Here I know str is a character array so it will have a base address, and thus will not produce a compilation error. But why does the absence of & for the argument a not result in a compilation error?
Also str gives correct output, but the integer is always producing the value -28770 as the output. Why is this?
scanf has the prototype:
int scanf(const char *fmt, ...);
The ... means that any number of arguments of any type may be specified after fmt. Hence it is the responsibility of the caller, not the compiler, to ensure that the provided arguments match what the function will be expecting.
int scanf(const char *format, ...);
This is the prototype for scanf. First argument is char* and other arguments are variable lengths. So no error will be generated.
As Umamahesh P wrote, you won't get a compilation error, because scanf is a variable-argument function. As to what happens when you run the program, it is what the C standard calls "undefined behaviour". Anything can happen. You need to look at what happens at the machine-instruction and memory address level to see what exactly scanf does with the integer value you gave it instead of a pointer.
You can get a compiler warning, depending on what compiler you use and what options you specify.
Also even if it tries to show those warnings, your compiler will be totally unable to do it if you use vscanf() or if you use a dynamic string as your format parameter.
For instance, this is the output I get using mingw-64 gcc 4.5.4:
gcc -Wall -o small.exe small.c
small.c:7:3: warning: format '%d' expects type 'int *', but argument 3 has type 'int'
small.c:7:8: warning: 'a' is used uninitialized in this function
Just add -Werror option to turn these warnings into errors.
I'm writing a program for converting temperatures and I have most of it written. When I compile and run the program, it doesn't do the calculations, doesn't seem to recognise the C/F choice and it isn't working out the reset part either.
What am I doing wrong?
#include <stdio.h>
#include <ctype.h>
float promptTemp(float kelvin)
{
printf("Please enter a sample temperature in degrees Kelvin:\n");
float convertFahrenheit(float temp)
{
}while(reset == 'y');
return(0);
}
The problem in your code is
promptTemp(temp);
and
promptConvert(convert);
you're neither
passing the pointer to variables as argument
collecting the return value.
So,
if(convert == 'c')
is esseentially using (reading) an uinitialized variable convert which in turn invokes undefined behaviour.
Please be aware that the values of the variables from your main function are changing inside your functions, because you are only passing a copy, and only that copy is modified inside the function and then lost. ( even though they have the same name ).
Try to pass the parameters as references or pointers.
You are not storing the return value of the function in the main function:
promptTemp(temp);/promptConvert(convert);
try result = promptTemp(temp);
and also you are not passing anything to the
promptTemp() function
There are a few things that need to be modified:
promptConvert(convert);
It isn't doing anything to convert variable. If you want the value returned from the function to be stored in the function, do this:
convert = promptConvert(convert);
If you want the function to modify the value of variable passed to it, do this:
char promptConvert(char &convert) //pass by reference
Similarly for other functions, like:
temp = convertCelsius(temp);
or
float convertCelsius(float &temp)
There are other functions which need the same modification too, like float convertFahrenheit(float temp)
By using a decent compiler, all the problems in this code will be revealed. One example of such a compiler is GCC. Get that one and then use it properly:
gcc -std=c11 -pedantic-errors -Wall -Wextra
Compiler output:
C:\tmp>gcc test.c -std=c11 -pedantic-errors -Wall -Wextra
test.c: In function 'promptConvert':
test.c:17:5: warning: statement with no effect [-Wunused-value]
tolower(convert);
^
test.c: In function 'promptReset':
test.c:72:5: warning: statement with no effect [-Wunused-value]
tolower(reset);
^
test.c: In function 'main':
test.c:87:9: warning: 'temp' is used uninitialized in this function [-Wuninitial
ized]
promptTemp(temp);
^
test.c:89:9: warning: 'convert' is used uninitialized in this function [-Wuninit
ialized]
promptConvert(convert);
^
test.c:100:9: warning: 'reset' is used uninitialized in this function [-Wuniniti
alized]
promptReset(reset);
^
So in addition to the bugs already pointed out in other answers, you also don't store the return value of tolower(). Should have been convert = tolower(convert);
I am very new to C Programming and have a doubt... I've been asked to find errors in certain segments of C code... and this segment has me a bit confused so would appreciate the help...
int main(void)
{
int myInt = 5;
printf("myInt = %d");
return 0;
}
As far as i understand there is nothing wrong in this code. What i wanna know is why is this statement printing out a random number ??
The output i get is
myInt = 1252057154
Would appreciate the help... Thanks
You should read more about C programming.
And you should enable all warnings and debugging when compiling. With GCC, this means gcc -Wall -Wextra -g (on Linux at least).
When compiling with
gcc -Wall -Wextra -g john.c -o john
I am getting the following warnings:
john.c: In function ‘main’:
john.c:4:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
john.c:4:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
john.c:4:5: warning: format ‘%d’ expects a matching ‘int’ argument [-Wformat]
john.c:3:9: warning: unused variable ‘myInt’ [-Wunused-variable]
So the correction is simple:
/* file john.c */
#include <stdio.h>
int main(void)
{
int myInt = 5;
printf("myInt = %d\n", myInt);
return 0;
}
which gets compiled without warnings.
Notice the \n at the end of printf format string. It is important.
Always enable all the warnings the compiler can give you and trust the compiler, so correct your code till no warnings is given.
And learn to use the debugger (e.g. gdb on Linux).
The behavior you observed is undefined behavior; anything could happen with a standard conforming implementation of C (even an explosion).
Happy hacking.
printf (and similarly scanf) works like this:
Let's say you issue a call to printf
printf("%d some text %f %u %hu some more text\n", arg1, arg2, arg3, arg4)
printf goes over the format string and replaces %? with an argument, based on ?
%d some text %f %u %hu some more text
| | | |
arg1 arg2 | arg4
arg3
Now the thing with functions taking variable number of arguments is that, they don't know if the arguments exist, that's why they just take data from a specific part of the stack based on the format string. If you write:
printf("%d %f %u\n");
it reads three non existing data from the stack, most probably get the values stored when calling the function (values that should be hidden from you)
Well, if it's printing something wrong, the problem is in the printf call:
printf("myInt = %d");
Which arguments you're expected to pass?
It should be this:
printf("myInt = %d",myInt);
If you don't include the variable, then it basically pulls a random chunk of memory in. In addition, it might cause more wierd stuff to happen if you do this with a larger chunk of code. Always make sure that you have as many variables from a printf statement as you need, or bad stuff will result.
printf is a function that receives one or more arguments.
In your case it received only one argument (which is legal) but the argument containes %d which tells printf to take the second argument instead of the %d.
printf takes the "second argument" from the stack, and because only one argument was pushed to the stack (the string), it uses the return address as the second argument.
int main(void)
{
int myInt = 5;
printf("myInt = %d",myInt);
return 0;
}
The only change in the code is I added myInt variable in the printf statement if you see at the end.Whenever a variable is assigned some value it can be displayed only by passing it to the printf() function with the corresponding type specifier.Its a rule in C.
#include <stdlib.h>
#include <stdio.h>
main()
{
const char* str_int = "777";
const char* str_float = "333.3";
int i = atoi(str_int);
float f = atof(str_float);
printf("%s %s", i, f);
}
I have tried several bits of example code I‛ve found online, and all of them cause bus errors. Why is this happening?
Your printf is incorrect. Try this instead:
printf("%d %f", i, f);
The problem is that your format specifiers are %s, which expect strings. But you gave it an intand a float. Therefore the result is undefined behavior.
The reason why it's crashing is because printf will try to read the parameters as strings (which are pointers) and deference them as such, but they are invalid pointers.
Here's a reference on printf and its format specifiers:
http://www.cplusplus.com/reference/clibrary/cstdio/printf/
Please take the habit of asking warnings from your compiler. With gcc it is the -Wall option and (on Linux/Debian/Sid gcc 4.6) I'm getting with your example file david.c using the gcc -Wall -g -o david david.ccommand:
david.c:4:1: warning: return type defaults to 'int' [-Wreturn-type]
david.c: In function 'main':
david.c:11:5: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'int' [-Wformat]
david.c:11:5: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'double' [-Wformat]
david.c:12:1: warning: control reaches end of non-void function [-Wreturn-type]
A newbie should correct his code till the compiler gives no more warnings. There are very very rare cases when leaving a warning is acceptable (it should happen less than once a year for a seasoned C programmer).
It's not, printf is. You're telling printf that you're passing it two strings ("%s"), when in fact you're passing an int and a float. It should be:
printf("%d %f", i, f);
Otherwise it'll treat the two arguments on the stack as strings (ie. char*).
Since two char*s haven't been passed as promised, when it tries to print the values of what it thinks are two strings on the stack, it'll cause undefined behaviour and potentially crash. This is most likely because the pointers it's trying to dereference are invalid and don't in fact point to a valid address.
printf has no way of telling if the arguments you're passing are correct, your compiler warnings however will. Turn up your compiler warnings.
Read here for more about warning options with gcc (if that's what you're using): http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Read here for more about the format specifiers (ie. %s, %d): http://www.cplusplus.com/reference/clibrary/cstdio/printf/
Printf is not correct.Change it to
printf("%d,%f",i,f);
Refer this link to understand the printf syntax clearly:
http://www.codingunit.com/printf-format-specifiers-format-conversions-and-formatted-output