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.
Related
I have really simple code to understand command line arguments parsing of main in C language:
#include <stdio.h>
int main(int argc, char* argv[]){
for(int i=1; i < argc; i++)
printf("%d\n", argv[i]);
printf("Number of arguments: %d\n", argc);
}
Having compiled and executed in a terminal passing 3 integers (eg. 1, 2, 3), I obtain the following strange result:
1175842993
1175842995
1175842997
Number of arguments: 4
I know that the solution is lying right straightforwardly towards my eyes, but it's been a hour that I cannot actual figure it out! Any hints? Thanks!
Dereference your pointer:
printf("%d\n", *argv[i]);
You may also be a little surprised, as you will get a numerical value represented by the (first) character printed; for instance for 1 it is 49.
In general you can tell your compiler to tell you a bit more by enabling more warnings. For instance gcc -Wall would tell you:
warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘char *’ [-Wformat=]
printf("%d\n", argv[i]);
Which would actually be a pretty solid hint.
And a side note: if you declare your main as int, you should return one too. ;) (But see EDIT2 for details).
EDIT: I guess I should have mentioned that with the actual output surprise in the second paragraph.
If verbatim reprint of the argument(s) is what you actually wanted. You'd use %s in your formatting string as Jonathan Leffler pointed out in the comment. In that case, you want the argument passed to be pointer to a string again (i.e. you do not use the * dereference operator).
EDIT2: As pointed out by Antti Haapala regarding the closing "Side note".
When using C99 or C11 you do not have to explicitly return (a value) for your main (and we're talking about main) that has been declared to return int. In that case default of 0 will be assumed. You really only need to do that for when adhering to C89 standard or other functions. For sake of simplicity though and/or when not sure what your target compiler configuration is, you won't be wrong being (type) consistent between your declared and actually returned value type. And again. gcc -Wall for example would let you know about that.
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 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.
The program is as follows:
#include<stdio.h>
int main()
{
int a[7]={1,2,3,4};
printf("%d%d%d%d%d",(*a),*(&*a),a[*a*0],*a);
return 0;
}
The Output on codepad.org is as follows:
11110
The Output on ideone.com is as follows:
1111-1074526944 where -1074526944 keeps varying every execution
I executed it on my personal gcc output is: 11110 i dont have the latest gcc
In the printf(); statement i am not concerned about the first four %d's because its totally obvious.
its the fifth %d i am concerned about. Why does it give such an output?
It tries to access whatever data happened to be on the stack of the call to printf() at the offset where a supposed "fifth parameter" would be, which your call to the function obviously has not provided.
To get a feel for it, learn how to write variadic functions.
To really understand it, you'd have to learn assembly.
To avoid such programming mistakes, use the -Wall parameter, which would have told you:
$ gcc -Wall main.c
main.c: In function ‘main’:
main.c:5:4: warning: format ‘%d’ expects a matching ‘int’ argument [-Wformat]
#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