I am trying to compile and run a simple C program from my Terminal. This is my code:
#include <stdio.h>
//integers that are 3n, 3n + 1, and 3n + 2
int main(){
int n,i,a,b,c;
scanf("%d", &n);
for (;n>0;n--) {
scanf("%d", &i);
if(n%3==0){a+=1;}
if(n%3==1){b+=1;}
if(n%3==2){c+=1;}
}
printf("%d %d %d", &a,&b,&c);
return 0;
}
After compiling it one time it generates this warning:
warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
I don't understand why it is generating that warning because I am not assigning any pointer variables. Why is it generating it?
Also, after compiling it a couple of times more my c file is turning into symbols. I don't understand why this is happening.
The name of my file is 73.c and this is how I'm compiling it on Terminal:
gcc 73.c -o 73.c
After that my file in converted to something like this (lines and lines of this):
œ˙Ì˛����Ä��������Ö� ��������H���__PAGEZERO��������������������������������������������������������(��__TEXT����������������������������������������������������__text����������__TEXT����������0�����˝�������0���������������Ä������������__stubs���������__TEXT����������.������������.��������������Ä�����������__stub_helper���__TEXT����������<�����$�������<���������������Ä������������__cstring�������__TEXT����������`������������`�����������������������������__unwind_info���__TEXT����������l�����H�������l������������������������������__eh_frame������__TEXT����������∏�����#�������∏��������������������������������Ë���__DATA��������������������������������������������������__nl_symbol_ptr�__DATA���������������������������������������������������__la_symbol_ptr�__DATA����������������������������������������������������H���__LINKEDIT������� ������������� ������`��������������������"��Ä0���� ����� ������������� �� ���# ��0���������∏ ����� !��#���
I really don't have any idea of what's going on. I've been at it for a long time now, I know it shouldn't be that hard but I really don't know what's wrong. Somebody have any idea of what might be happening?
There are two major things that are wrong here:
You try to print the address of variables a, b and c.
You invoke Undefined Behavior, but not initializing your
counters to 0.
You want to print the integers, so change this:
printf("%d %d %d", &a,&b,&c);
to this:
printf("%d %d %d", a, b, c);
I also added some spaces, but that's just to beautify the code, to make it more readable, it won't affect the execution.
You don't want to print the addresses! That's why you get the warning. Read more here: What is the difference between the * and the & operators in c programming?
As achelper, mentioned, you don't compile your program as you should (but that's not the problem of the code), but it's something you should get used to. I will demonstrate what I did to compile me program (I also like to use -Wall flag, which enables all warnings):
C02QT2UBFVH6-lm:~ gsamaras$ nano main.c
C02QT2UBFVH6-lm:~ gsamaras$ gcc main.c -Wall -o main
main.c:13:22: warning: format specifies type 'int' but the argument has type
'int *' [-Wformat]
printf("%d %d %d", &a,&b,&c);
~~ ^~
main.c:13:25: warning: format specifies type 'int' but the argument has type
'int *' [-Wformat]
printf("%d %d %d", &a,&b,&c);
~~ ^~
main.c:13:28: warning: format specifies type 'int' but the argument has type
'int *' [-Wformat]
printf("%d %d %d", &a,&b,&c);
~~ ^~
main.c:11:16: warning: variable 'c' is uninitialized when used here
[-Wuninitialized]
if(n%3==2){c+=1;}
^
main.c:5:16: note: initialize the variable 'c' to silence this warning
int n,i,a,b,c;
^
= 0
main.c:10:16: warning: variable 'b' is uninitialized when used here
[-Wuninitialized]
if(n%3==1){b+=1;}
^
main.c:5:14: note: initialize the variable 'b' to silence this warning
int n,i,a,b,c;
^
= 0
main.c:9:16: warning: variable 'a' is uninitialized when used here
[-Wuninitialized]
if(n%3==0){a+=1;}
^
main.c:5:12: note: initialize the variable 'a' to silence this warning
int n,i,a,b,c;
^
= 0
6 warnings generated.
C02QT2UBFVH6-lm:~ gsamaras$ ./main
2
1
2
1461300256 1461300252 1461300248C02QT2UBFVH6-lm:~ gsamaras$
In general, when in doubt, treat warnings as errors, so let's debug that code together, it will be fun. Pro-tip: Start from the first warning and resolve it. After that, the next warnings may be related, thus gone without having you really reading them!
After applying my suggestion, all the warnings related with what you described in your question are gone. Only the uninitialized variable ones are left.
That's easy, just initialize your variables to some initial value, like -1, if that makes sense of course.
In your case though, you use a, b and c as counters! So you must initialize them to 0, otherwise you are starting adding your values to garbage values, and that invokes Undefined Behavior!
So do change this:
int n,i,a,b,c;
to this:
int n, i, a = 0, b = 0, c = 0;
Without the initialization of the counters, I am getting, on my machine, now
C02QT2UBFVH6-lm:~ gsamaras$ ./main
2
1
2
1505029184 1 1C02QT2UBFVH6-lm:~ gsamaras$
You see that printf() gives me some garbage, while after initializing my counters to 0, I got:
C02QT2UBFVH6-lm:~ gsamaras$ ./main
2
1
2
0 1 1C02QT2UBFVH6-lm:~ gsamaras$
The points mentioned by gsamaras are correct, you should use :
printf("%d %d %d", a, b, c);
The syntax you were using is used in
scanf (pass address of the variable where the data is need to be filled.)
Also initialize variables while defining.
Regarding compilation:
The name -o specifies the output file generated after compilation thus it is overwriting your source code (i.e., 73.c).
If you omit -o, the default output file is generated as a.out. So for compiling you can use following and run the program as ./a.out:
gcc 73.c
man gcc quotes:
-o file
Place output in file file. This applies to whatever sort of output is being produced, whether it be an executable file, an object file, an assembler
file or preprocessed C code.
If -o is not specified, the default is to put an executable file in a.out, the object file for source.suffix in source.o, its assembler file in source.s,
a precompiled header file in source.suffix.gch, and all preprocessed C source on standard output.
Related
I am a new learner for c.
And I can't see what on earth this difference is.
Thank you for your help!
#include<stdio.h>
int main(void)
{
char a[9];
scanf("%s",&a);//scanf("%s",a)
printf("%s",&a);//printf("%s",a) they all can run correctly!
for(int i=0;i<9;i++)
{
printf("%c;",a[i]);
}
return 0;
}
With &, you are invoking undefined behavior for type mismatch: %s expect char*, but &a here has type char(*)[9] (a pointer to 9-elemnent character array).
In typical environment, pointers are implemented as simple memory addresses.
Despite of type mismatch, the address of the array &a and its first element a will be the same (same size and same value), so there are high chance to work well.
Allow a little analogy
Imagine you live in a (semi-)transparent world and you have a few differently colored laser pointers.
You use red lasers to point at people, blue lasers to point at planes, yellow lasers to point at mobile phones, ..., ...
It's illegal to mismatch pointers and objects (undefined behaviour in C slang), so no yellow lasers on planes, no blue lasers on people, ...
Now imagine you are using a yellow laser to point to a mobile phone of someone travelling in a plane, and you ask a color-blind friend (the printf()) what plane the pointer points to. Your friend does not care about the color and, wrongly, says it's whatever plane the yellow laser shines on.
But the responsible person for the error is you. You tricked your friend!
Don't lie to the compiler
regarding:
#include<stdio.h>
int main(void)
{
char a[9];
scanf("%s",&a);//scanf("%s",a)
printf("%s",&a);//printf("%s",a) they all can run correctly!
for(int i=0;i<9;i++)
{
printf("%c;",a[i]);
}
return 0;
}
When compiling, always enable the warnings, then fix those warnings. ( for gcc, at a minimum use: -Wall -Wextra -Wconversion -pedantic -std=gnu11 ) Note: other compilers use different options to produce the same results.
The posted code results in three(3) warning messages from the compiler
gcc -O1 -ggdb -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled2.c"
untitled2.c: In function ‘main’:
untitled2.c:5:13: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[9]’ [-Wformat=]
scanf("%s",&a);//scanf("%s",a)
~^ ~~
untitled2.c:6:14: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[9]’ [-Wformat=]
printf("%s",&a);//printf("%s",a) they all can run correctly!
~^ ~~
untitled2.c:5:5: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result [-Wunused-result]
scanf("%s",&a);//scanf("%s",a)
^~~~~~~~~~~~~~
Compilation finished successfully.
The final statement: "Compilation finished successfully.", when there are warning messages, only means the compiler produced some 'work around' for the problems, That does not mean the compiler produced the code that you wanted.
regarding:
for(int i=0;i<9;i++)
{
printf("%c;",a[i]);
}
if the input from the user was less than 8 bytes, then some trash/garbage bytes will be output.
Suggest:
for( int i=0; a[i]; i++ ) // stops on NUL byte
{
printf("%c;",a[i]);
}
so only the user input and not the uninitialized bytes be output.
Even better, since the call to scanf() with %s will have NUL terminated the input is to use the single statement:
printf( "%s\n", a );
OT: When calling any of the scanf() family of functions, always check the returned value (not the parameter values) to assure the operation was successful. Note: those functions return the number of successful 'input format conversion' specifiers (or EOF). Suggest: (after syntax corrections and error checking added)
if( scanf("%8s",a) != 1 )
{ // error occurred
fprintf( stderr, "scanf for input data failed\n" );
exit( EXIT_FAILURE );
}
This question already has answers here:
Does this self-assignment do something sensible?
(4 answers)
Compiler not detecting obviously uninitialized variable
(4 answers)
Closed 5 years ago.
While debugging a program of mine, I stumbled upon a weird behaviour of the gcc compiler. I don't know what's the correct title to describe this, but take a look at the code below.
Basically, I had a function which received a void* arg as an argument. It then casted it to a pointer of another type, HTTPRequest*. However, I casted the wrong variable, so the code looked like
void someCallback(void* arg) {
HTTPRequest* req = (HTTPRequest*) req;
FreeRequest(req);
//re-setup request, other stuff..
}
The program then crashed within FreeRequest with a SIGSEGV when it tried to derefrence the pointer. Upon further inspection, req always a had a value of NULL.
It took me a while to realize that the cast I did was just done on the wrong variabe - it should have been
HTTPRequest* req = (HTTPRequest*) arg;
Then it all worked. I was however baffled that gcc allowed me to not only compile this code, but throw no warning whatsoever at this line.
Consider the minimal example
#include <stdlib.h>
#include <stdio.h>
void someFunc(void* arg) {
int* a = (int*) a;
printf("a = %p\n", a);
printf("*a = %d\n", *a);
}
int main() {
int b = 42;
someFunc(&b);
return 0;
}
Compiled with
gcc -Wall -Wextra -Wpedantic -o test -O0 test.c && test.exe
Compiler outputs
test.c: In function 'someFunc':
test.c:7:9: warning: format '%p' expects argument of type 'void *', but argument 2 has type 'int *' [-Wformat=]
printf("a = %p\n", a);
^
test.c:4:21: warning: unused parameter 'arg' [-Wunused-parameter]
void someFunc(void* arg) {
^
And the program outputs:
a = 0061FFCC
*a = 6422500
With optimization at atleast O1 it outputs however:
gcc -Wall -Wextra -pedantic -o test -O1 test.c && test.exe
test.c: In function 'someFunc':
test.c:7:9: warning: format '%p' expects argument of type 'void *', but argument 2 has type 'int *' [-Wformat=]
printf("a = %p\n", a);
^
test.c:4:21: warning: unused parameter 'arg' [-Wunused-parameter]
void someFunc(void* arg) {
^
And outputs
a = 00000000
Then hangs.
So the question is: Why does gcc allow the compilation of expressions of the above form? This is obviously undefined behaviour. Then why are there no warnings about this, even with all warnings enabled?
Why does gcc allow the compilation of expressions of the above form? This is obviously undefined behaviour.
Because the standard allow this. Undefined behavior allow compiler to optimize code write in C. You can read this excellent article from llvm developer.
Then why are there no warnings about this, even with all warnings enabled?
-Wall -Wextra don't active all warning in gcc. clang has -Weverything but, gcc don't have such option.
Compiler are not force to print a warning message for everything. There are few warning that a compiler must print if it want to be standard compliant.
What you do is undefined behavior and this is not mandatory in the standard to print a warning.
clang 4.0.0 has a warning for this -Wuninitialized:
warning: variable 'a' is uninitialized when used within its own initialization [-Wuninitialized]
int* a = (int*) a;
gcc 7.1.1 has a warning for this -Winit-self:
warning: ‘a’ is used uninitialized in this function [-Wuninitialized]
int* a = (int*) a;
Note: Your cast is useless, C will promote any void * to the correct pointer type.
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.
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