Why did this code run still work,with '&' or without '&'? - c

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 );
}

Related

printf displays a different value

I've got a variable i that is initialized to 1, when I want to display it, it displays 6421788 instead of 1.
int i = 1;
printf("WELCOME: OUR AVAILABLE TRIPS:\n");//displaying trips
while(fgets(trip,sizeof(trip),StrdFile) != NULL)
{
printf("%i.",&i);//the problem
printf("%s\n",trip);
i++;
}
This is the part of the code that must be the problem. The display need to be :
1.\*info*
2.\*info*
but what I get is
6421788.\*info*
6421788.\*info*
also, I checked the value of i in the debugger and it's correct.
You're printing the address of i (kinda). Replace
printf("%i.",&i); // Address of `i`
with
printf("%i.",i); // Value of `i`
Enable and heed your compiler's warnings! With gcc, I use -Wall -Wextra -pedantic; it would have caught this error.
a.c:10:18: warning: format ‘%i’ expects argument of type ‘int’,
but argument 2 has type ‘int *’ [-Wformat=]
printf("%i.",&i);//the problem
~^ ~~
%ls
You are actually printing the number of the memory address which is reserved for your i variable .
Getting this address is done by adding the sign & before the variable name.
printf("%i",&i);
Will print the address of memory address reserved for your var i
printf("%i",i);
Will print the value in your var i .
Take a look here : https://documentation.help/C-Cpp-Reference/printf.html

Compilation on Terminal gives off pointer warning and strange symbols

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.

C printf printing random number

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.

Why does atoi() cause a bus error?

#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

GCC: why a -Wformat warning for this fprintf?

We cleaned up a large number of warnings. In several cases, we replaced %s with %d. Everything seemed OK until we realized that the generated code wouldn't compile - strings had been replaced by numbers.
NOTE: I had the wrong revision checked out when I did the copy&paste. The fprintf string has been edited!
GCC output
fedex_plus/classes.c:2425:3: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat]
lines 2424 and 2425:
fprintf(file, "\n//\t%s_ptr create_TIE();\n\tIDL_Application_instance_ptr create_TIE();\n",
ENTITYget_CORBAname(entity));
function ENTITYget_CORBAname:
const char *
ENTITYget_CORBAname (Entity ent)
{
static char newname [BUFSIZ];
strcpy( newname, ENTITYget_name(ent) );
newname[0] = ToUpper (newname [0]);
return newname;
}
My bet is that no declaration of ENTITYget_CORBAname is available at the fprintf spot. Should this be the case, it defaults to the implicit signature:
int ENTITYget_CORBAname(...);
hence the warning about the result type being an int.
Check your code with -Wimplicit (implied by -Wall), or try to put
const char *ENTITYget_CORBAname (Entity ent);
before the fprintf line and check if the warning disappears. If it does, then you're likely missing a header.
If you want to print a pointer value, use %p, if you want to print the string returned from the function, use %s. Don't use %d in any of this cases. See here.
I assume that ENTITY_GETCorbaName() returns a string, so if you want to print that, use %s. If you want to print it as pointer, use %p.
use %s in your printf to print that string or use %p in your printf to show pointer value you can also use %lld to prints its value

Resources