This is my basic C test program.
After I built it, I just entered negative number like -1, -2, etc. in console.
But the result is "oh", not "another number".
I don't know why this happens, because negative numbers should make the 'if' statement true.
int main(int argc, char* argv[]){
long int num;
scanf("%d", &num);
if(num ==1 || num < 0){
printf("another number\n");
}else{
printf("oh\n");
}
}
When you use the %d format string with scanf, the corresponding argument will be treated as int*. But you have passed a long int*. The value scanf stores will not be the same size as what your if statement reads.
Formally, you get undefined behavior. In practice, on most platforms scanf will write only part of the variable, and the rest will be left with an arbitrary value, with the usual bad effects on future use.
Use %ld for long variables, %d for ints. Change your code to one of these:
int num;
scanf("%d", &num);
or
long int num;
scanf("%ld", &num);
/tmp$ gcc -Wall foo.c
foo.c: In function ‘main’:
foo.c:4:5: warning: implicit declaration of function ‘scanf’ [-Wimplicit-function-declaration]
foo.c:4:5: warning: incompatible implicit declaration of built-in function ‘scanf’ [enabled by default]
foo.c:4:5: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘long int *’ [-Wformat]
foo.c:7:9: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
foo.c:7:9: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
foo.c:9:9: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
foo.c:11:1: warning: control reaches end of non-void function [-Wreturn-type]
fix the causes of those warnings and all the bugs will go away.
Related
This question already has answers here:
What header should I include for memcpy and realloc?
(2 answers)
warning: incompatible implicit declaration of built-in function 'strlen' and 'strcpy' [duplicate]
(1 answer)
Closed 5 years ago.
#include<stdio.h>
struct stud
{
char name[20];
int mark;
int per;
char grad[5];
};
void main(){
int i,n;
printf("Enter number of students");
scanf("%d",&n);
struct stud s[n];
for(i=1;i<=n;i++)
{
printf("Enter name of student");
scanf("%d",s[i].name);
printf("Enter obtained marks");
scanf("%d",&s[i].mark);
s[i].per=s[i].mark/5;
}
for(i=1;i<=n;i++)
{
if(s[i].per>=80)
strcpy(s[i].grad,"A");
else if(s[i].per>=60)
strcpy(s[i].grad,"B");
else if(s[i].per>=50)
strcpy(s[i].grad,"C");
else if(s[i].per>=40)
strcpy(s[i].grad,"D");
else
strcpy(s[i].grad,"F");
}
for(i=1;i<=n;i++)
{
printf("&s",s[i].name);
printf("&d",s[i].mark);
printf("&d",s[i].per);
printf("&s",s[i].grad);
}
}
When executing this code it's showing error :
main.c: In function ‘main’:
main.c:25:10: warning: implicit declaration of function ‘strcpy’ [-Wimplicit-function-declaration]
strcpy(s[i].grad,"A");
^~~~~~
main.c:25:10: warning: incompatible implicit declaration of built-in function ‘strcpy’
main.c:25:10: note: include ‘<string.h>’ or provide a declaration of ‘strcpy’
main.c:27:11: warning: incompatible implicit declaration of built-in function ‘strcpy’
strcpy(s[i].grad,"B");
^~~~~~
main.c:27:11: note: include ‘<string.h>’ or provide a declaration of ‘strcpy’
main.c:29:11: warning: incompatible implicit declaration of built-in function ‘strcpy’
strcpy(s[i].grad,"C");
^~~~~~
main.c:29:11: note: include ‘<string.h>’ or provide a declaration of ‘strcpy’
main.c:31:10: warning: incompatible implicit declaration of built-in function ‘strcpy’
strcpy(s[i].grad,"D");
^~~~~~
main.c:31:10: note: include ‘<string.h>’ or provide a declaration of ‘strcpy’
main.c:33:10: warning: incompatible implicit declaration of built-in function ‘strcpy’
strcpy(s[i].grad,"F");
^~~~~~
main.c:33:10: note: include ‘<string.h>’ or provide a declaration of ‘strcpy’
What's the error here ?
scanf("%d",s[i].name); is undefined behavior. It will be "%s" format specifier.
And printf("%s",s[i].name) not &s.
Include string.h header file.
Also array index out of bound while getting input. Also undefined behavior. Array indices start from 0. All loop would be for(i=0;i<=n-1;i++)
and include header like this:
#include <string.h>
for(i=0;i<=n-1;i++)
{
printf("Enter name of student");
scanf("%s",s[i].name);
printf("Enter obtained marks");
scanf("%d",&s[i].mark);
s[i].per=s[i].mark/5;
}
Another change
for(i=1;i<=n;i++)
{
printf("%s",s[i].name);
printf("%d",s[i].mark);
printf("%d",s[i].per);
printf("%s",s[i].grad);
}
I tried to using two different functions from sting.h header file (without including it) strlen() and strtok(). Strlen executed successfully without any error (but some warnings), strtok failed at runtime. Why is it that strlen() function worknig gine but not strtok() if I don't include the header file? I suppose there is something in the linking process that I don't understand. Please clarify for such behavior. However, the program terminates successfully if I print a as '%c' instead of '%s' (strtok returns a garbage value).
CODE:
int main()
{
char string[] = "This is a String";
printf("\nLength of sting is %d\n",strlen(string));
}
WARNINGS:
hello.c: In function ‘main’:
hello.c:4:2: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
hello.c:4:37: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default]
hello.c:4:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat]
OUTPUT:
$ ./a.out
Length of sting is 16
CODE:
int main()
{
char string[] = "This is a String";
printf("\nLength of sting is %d\n",strlen(string));
char *a = strtok(string," ");
printf("%s",a);
}
WARNINGS:
$ gcc hello.c
hello.c: In function ‘main’:
hello.c:4:2: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
hello.c:4:37: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default]
hello.c:4:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat]
hello.c:5:12: warning: initialization makes pointer from integer without a cast [enabled by default]
OUTPUT:
$ ./a.out
Length of sting is 16
Segmentation fault (core dumped)
The linking is done implicitly for most of the C standard library. You just have to include the headers of what you use (that's the warnings).
When you don't, your compiler (which is compiling your code as ANSI C) assumes the functions return int, instead of their documented return types. Your program has undefined behavior because of that. Always heed warnings!
You must include the headers string.h and stdio.h.
The first program works because you were lucky enough in that strlen is supposed to return an integer (a size_t to be exact, but it appears on your system the value representation for integers and size_t lets the program slide through).
The second fails because strtok returns a char* but it's assumed an int due to your missing include directives. int and char* are not compatible types, so the "pointer" you get isn't valid.
Sting is a singer, not a C header... Still, the problem is that in C, when you use functions that were not declared, the compiler guesses them to have the types of the arguments you first pass to them and returning an int.
That's the reason why you get all these warnings: several undeclared functions you use don't actually have the deduced signature (although they are not too wrong, and end up working), and the real strtok returns a pointer, not an int (the warning in facts says that you are assigning an int to a pointer without a cast). The crash you are getting most probably comes from the fact that the original pointer is 64 bit, but is truncated to 32 bit when is erroneously considered an int before being assigned to a.
Still, the point to take home is: include headers and don't ever rely on implicit function declaration. It's a dangerous mess that exists only for backward compatibility reasons.
I am trying to use the strtoul function, but as shown below it is returning an unexpected value (adding ff's in the beginning):
#include <stdio.h>
#include <string.h>
#include <limits.h>
main() {
unsigned long temp ;
char *err;
temp = strtoul("3334444444",&err,10);
if (temp > UINT_MAX) {
printf("%lx %x %x\n",temp,3334444444,UINT_MAX);
}else
printf("%lx %x\n",temp,3334444444);
}
$./a.out
ffffffffc6bf959c c6bf959c ffffffff
The above output corresponds to the if part being true, though I expect the else part to get executed here. Can anyone please explain why strtoul is behaving like this? Why does it return ffffffffc6bf959c rather than just c6bf959c? If I use "333444444" (i.e. just one 4 less) rather than "3334444444" in the above code, then I get the correct output (i.e. 13dff55c 13dff55c) corresponding to the else part.
Note : As pointed by melpomene in his reply below, stdlib.h header file should have been included and that will resolve the issue. Can anyone please let me know what is being done by the program by assuming the incorrect return type (int in this case) during compile time which can't be undone (or atleast it is not getting undone in this case) even after knowing the correct return type (unsigned long in this case) during link time ? In short, i want to know how c6bf959c is getting converted to ffffffffc6bf959c because of prototype not provided.
Compiling your code with gcc with warnings enabled gives:
try.c:5:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
main() {
^~~~
try.c:5:1: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
try.c: In function ‘main’:
try.c:8:12: warning: implicit declaration of function ‘strtoul’ [-Wimplicit-function-declaration]
temp = strtoul("3334444444",&err,10);
^~~~~~~
try.c:8:5: warning: nested extern declaration of ‘strtoul’ [-Wnested-externs]
temp = strtoul("3334444444",&err,10);
^~~~
try.c:10:22: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 3 has type ‘long long int’ [-Wformat=]
printf("%lx %x %x\n",temp,3334444444,UINT_MAX);
^
try.c:12:22: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 3 has type ‘long long int’ [-Wformat=]
printf("%lx %x\n",temp,3334444444);
^
The main problem is implicit declaration of function ‘strtoul’, indicating that the function is not declared (and thus assumed to return int) because you forgot to #include <stdlib.h>. Adding the missing #include fixes the value of temp.
But you should also have a look at the warnings reported for printf and fix those.
I'm trying to write an MPI worker in C that will communicate with the MPI master, written in python. The master will send out scatters and gathers, and the C worker should receive those and return variables via gather. The problem is, I'm having trouble successfully writing the worker file.
(The reason the worker is in C is because this code is a skeleton to wrap around preexisting python and C programs.)
Here is the code I've written:
#include <stdio.h>
#include <mpi.h>
MPI_Comm comm;
MPI_Comm_get_parent(&comm);
int myid, world_size, size;
int root = 0;
int* endloop = malloc(sizeof(int));
int nelements1 = 1E3;
int nelements2 = 1E6;
float* input = malloc(sizeof(float) * nelements1);
float output[nelements2];
int randomarray(){
float array[nelements2];
srand(time(NULL));
for( i = 0; i < nelements2; i++ ){
array[i] = rand() % 0 + 1E6;
}
return array;
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
MPI_Comm_remote_size(comm, &size);
output = randomarray();
MPI_Scatter(endloop, 1, MPI_INT, root, comm);
while ( endloop[0] < 1) {
MPI_Barrier(comm);
MPI_Scatter(input, nelements1, MPI_FLOAT, root, comm);
MPI_Barrier(comm);
MPI_Gather(output, nelements2, MPI_FLOAT, root, comm);
MPI_Scatter(endloop, 1, MPI_INT, root, comm);
}
MPI_Finalize();
And the error output when I attempt to compile is:
maddie#exo:~/code/bart_commloop$ mpicc worker.c -o worker
worker.c:5:21: error: expected declaration specifiers or ‘...’ before ‘&’ token
worker.c:9:16: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
worker.c:9:1: error: initializer element is not constant
worker.c:12:1: error: initializer element is not constant
worker.c:13:7: error: variably modified ‘output’ at file scope
worker.c: In function ‘randomarray’:
worker.c:18:7: error: ‘i’ undeclared (first use in this function)
worker.c:18:7: note: each undeclared identifier is reported only once for each function it appears in
worker.c:19:21: warning: division by zero [-Wdiv-by-zero]
worker.c:22:2: warning: return makes integer from pointer without a cast [enabled by default]
worker.c:22:2: warning: function returns address of local variable [enabled by default]
worker.c:28:8: error: incompatible types when assigning to type ‘float[1]’ from type ‘int’
worker.c:30:1: warning: passing argument 4 of ‘MPI_Scatter’ makes pointer from integer without a cast [enabled by default]
/usr/lib/openmpi/include/mpi.h:1197:20: note: expected ‘void *’ but argument is of type ‘int’
worker.c:30:1: warning: passing argument 5 of ‘MPI_Scatter’ makes integer from pointer without a cast [enabled by default]
/usr/lib/openmpi/include/mpi.h:1197:20: note: expected ‘int’ but argument is of type ‘MPI_Comm’
worker.c:30:1: error: too few arguments to function ‘MPI_Scatter’
/usr/lib/openmpi/include/mpi.h:1197:20: note: declared here
worker.c:34:2: warning: passing argument 4 of ‘MPI_Scatter’ makes pointer from integer without a cast [enabled by default]
/usr/lib/openmpi/include/mpi.h:1197:20: note: expected ‘void *’ but argument is of type ‘int’
worker.c:34:2: warning: passing argument 5 of ‘MPI_Scatter’ makes integer from pointer without a cast [enabled by default]
/usr/lib/openmpi/include/mpi.h:1197:20: note: expected ‘int’ but argument is of type ‘MPI_Comm’
worker.c:34:2: error: too few arguments to function ‘MPI_Scatter’
/usr/lib/openmpi/include/mpi.h:1197:20: note: declared here
worker.c:36:2: warning: passing argument 4 of ‘MPI_Gather’ makes pointer from integer without a cast [enabled by default]
/usr/lib/openmpi/include/mpi.h:1058:20: note: expected ‘void *’ but argument is of type ‘int’
worker.c:36:2: warning: passing argument 5 of ‘MPI_Gather’ makes integer from pointer without a cast [enabled by default]
/usr/lib/openmpi/include/mpi.h:1058:20: note: expected ‘int’ but argument is of type ‘MPI_Comm’
worker.c:36:2: error: too few arguments to function ‘MPI_Gather’
/usr/lib/openmpi/include/mpi.h:1058:20: note: declared here
worker.c:37:2: warning: passing argument 4 of ‘MPI_Scatter’ makes pointer from integer without a cast [enabled by default]
/usr/lib/openmpi/include/mpi.h:1197:20: note: expected ‘void *’ but argument is of type ‘int’
worker.c:37:2: warning: passing argument 5 of ‘MPI_Scatter’ makes integer from pointer without a cast [enabled by default]
/usr/lib/openmpi/include/mpi.h:1197:20: note: expected ‘int’ but argument is of type ‘MPI_Comm’
worker.c:37:2: error: too few arguments to function ‘MPI_Scatter’
/usr/lib/openmpi/include/mpi.h:1197:20: note: declared here
worker.c:40:1: error: expected declaration or statement at end of input
The issue seems to be the formatting of my MPI calls, but I'm not sure what to fix there.
Any help would be greatly appreciated. Thank you!
I have absolutely no idea why it returns 2 for a=2 and b=2..
Any ideas?
#include <stdlib.h>
int main()
{
double a,b,c;
printf("a=");
scanf("%d", &a);
printf("b=");
scanf("%d", &b);
printf("c=");
scanf("%d", &c);
printf("x=%d", a+b);
return 0;
}
The specifier "%d" expects an integer and you are passing the address of a double. Using the wrong specifiers in scanf leads to undefined behavior.
Also, using the wrong specifier in printf is the same thing. Because printf takes a variable number of arguments a + b which is a double can't be converted to an integer.
%d is for reading integers, use %f or %lf for float/double.
printf should use something like %f instead of %d. The same for scanf.
If you want to accept a float input, use scanf (and printf) with the %lf formatting character, not %d (which is for integers).
The behavior of your current program is undefined, since the scanf calls are writing an integer to a float variable. Also, you're missing include <stdio.h> at the top of your program. To catch errors like these, turn on the warnings in your C compiler:
$ gcc so-scanf.c -Wall
so-scanf.c: In function ‘main’:
so-scanf.c:6:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
so-scanf.c:6:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
so-scanf.c:7:5: warning: implicit declaration of function ‘scanf’ [-Wimplicit-function-declaration]
so-scanf.c:7:5: warning: incompatible implicit declaration of built-in function ‘scanf’ [enabled by default]
so-scanf.c:7:5: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘double *’ [-Wformat]
so-scanf.c:9:5: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘double *’ [-Wformat]
so-scanf.c:11:5: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘double *’ [-Wformat]
so-scanf.c:13:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘double’ [-Wformat]