Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 days ago.
This post was edited and submitted for review 6 days ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
I've been told we somehow need them so the compiler can continue onwards without having read the definition yet.
Somehow we need them in order for the program to work properly, to avoid conflicts between functions.
Please explain.
If you're going to have separate compilation, meaning that the call versus the definition of a function might be in separate source files, compiled at different times, perhaps months or years apart, you need to decide how information passed to and returned from the function is going to be coordinated.
Let's cover the return value first. Functions can be declared to return int, or double, or char *, or just about any of C's other types. (There are one or two exceptions, types which it's impossible to return, but they needn't concern us here.) But for any given ABI, different values get returned in different ways. Integers and pointers might get returned in a general-purpose processor register. Floating-point values might get returned in a floating-point register. Structures might get returned in some specially-designated memory area. In any case, the called function is going to do the returning, but the calling function (compiled separately) is going to do something with the returned value, so it has to know how to emit the right code to do that. And the only way for it to know (again, under C's separate-compilation model) is the function declaration that indicated the return type. If the calling code thought the function was going to return an int, but the called function actually returned a double, it just wouldn't work, because the called function would place its return value in the spot where return values of type double go, and the calling code would fetch a value from the place where return values of type int go, and it would get indeterminate garbage instead.
Now let's talk about the arguments passed to the function. Again, the mechanisms behind argument passing can take several forms, depending on the type(s) of the argument(s). Again, mismatches are easy, but can cause serious problems. If the programmers writing calling code could be relied on to always pass the correct number of arguments, and of the correct types, we wouldn't need function prototypes — and indeed, that's how C was for the first few years of its life. These days, however, that risk is generally considered as unacceptable, and function prototypes are considered mandatory — by the language standard, by compilers, and by most C programmers. (You might still find a few holdouts, grumbling that prototypes are newfangled or unnecessary, but they're basically an ignorable minority.)
There's a remaining wrinkle concerning "varargs" functions such as printf. Since they don't accept a fixed number of fixed-type arguments, they can't have a prototype that specifies the types of those arguments in advance. An ellipsis ("...") in a function prototype indicates variable arguments that (a) can't be enforced by the compiler but that (b) do have the default argument promotions performed on them, to provide a little more regularity (basically, small types like char and int promoted to int, and float promoted to double). Varargs functions, too, are generally consider old-school and risky if not downright dangerous, and are not recommended for new designs, unless perhaps if they follow the pattern of printf, meaning that the compiler can peek at the format string (if constant) and do the programmer the favor of double-checking the arguments.
The requirements here have been evolving ever since C was invented, and (as discussed in the comments) are still changing. If you have specific questions about what's legal and what's not, what works and what won't, you might want to ask them explicitly, but the answer may depend on which version of C we're talking about.
We can get a good picture of most of the issues just by looking at the standard sqrt function. Suppose you say
double x = sqrt(144);
Once upon a time, that was doubly wrong. Once upon a time, without a function declaration in scope, sqrt would be assumed to return int, meaning that this call wouldn't work, because sqrt actually returns a double. (The compiler would emit code to fetch an int and convert it to the double required by x, but this would be meaningless since there's no int actually returned by sqrt to convert.) But, there's a second problem: sqrt accepts a double argument, which this code doesn't pass, so sqrt wouldn't even receive the correct value to take the square root of.
So, once upon a time, you absolutely needed
extern double sqrt();
(which you probably got from <math.h>) to tell the compiler that sqrt returned a double, and it was your responsibility to call
double x = sqrt(144.);
or
double x = sqrt((double)144);
to cause a double value to be passed.
Today, if you call sqrt out of a clear sky (that is, without a declaration in scope), the compiler is more likely to complain that there's no prototype in scope — that is, it will not quietly assume that sqrt returns int. And if there is a declaration in scope, it will be the prototype declaration
extern double sqrt(double);
which explicitly says that sqrt expects one argument of type double. So, today, the code
double x = sqrt(144);
works fine — the compiler knows to implicitly convert the int value 144 to double before passing it to sqrt.
If you did something really wrong, like calling sqrt(44, 55), in the old days you'd get no complaints (and a very wrong answer), while today you'll get an error saying you've passed too many arguments.
This is probably a longer answer than you were looking for, but in closing, there are two final points to make:
No one would claim that any of this makes perfect sense, or is the way you'd design things from scratch, today. We're living (as ever) with a number of imperfect compromises between modernity and backwards compatibility.
The "guarantees" apparently promised by function prototypes — namely, that automatic argument conversions will be performed if possible, and that compile-time errors will be emitted for gross mismatches — are not absolute, and still depend on a certain amount of programmer care, namely to ensure that the prototypes (upon which everything depends) are actually correct. This generally means putting them in .h files, included both by the caller and the defining source file. See also this question exploring how those vital conventions might be enforced.
Because C Compilers compile code row from top to bottom. If you gonna use any function in your main function you have two ways to do that.
You can code your function first then use main(Compiler code row from top to bottom so it will figure out there is a function)
Like you do you can use parameters to say "Hey there is a function that i made i will use that later" to Compiler.
Example:
Declaration without parameters. COMPILES.
Declaration without parameters and either without type. COMPILES BUT WARNING.
Call BEFORE definition (and no declaration). Compile error. ERROR.
Compiles perfectly (as #Vlad from Moscow pointed, neither parameters are needed in declaration):
1 #include <stdio.h>
2
3 int sum (); // no parameters declaration (if also omit type int, will compile but with warning
4
5 int main (void)
6 {
7 int numa = 2, numb = 3;
8
9 printf ("Sum %d + %d = %d\n", numa, numb, sum ( numa, numb ));
10
11 return 0;
12 }
13
14 int sum ( int numa, int numb )
15 {
16 return numa + numb;
17 }
output:
./ftype_def_dec
Sum 2 + 3 = 5
type int of function ommited (compiled but with warning):
gcc -o ftype_def_dec ftype_def_dec.c
ftype_def_dec.c:3:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
sum ();
^
1 warning generated.
Does not compile (if you omit declaration in a function called in main() BEFORE it's DEFINITION [every detail [types & what/how it does explicited]]):
1 #include <stdio.h>
2
3 // int sum ();
4
5 int main (void)
6 {
7 int numa = 2, numb = 3;
8
9 printf ("Sum %d + %d = %d\n", numa, numb, sum ( numa, numb ));
10
11 return 0;
12 }
13
14 int sum ( int numa, int numb )
15 {
16 return numa + numb;
17 }
gcc -o ftype_def_dec ftype_def_dec.c
ftype_def_dec.c:9:44: error: implicit declaration of function 'sum' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
printf ("Sum %d + %d = %d\n", numa, numb, sum ( numa, numb ));
^
1 error generated.
Because the compiler has to be able to know how your function can be called and used (i.e. what parameters it accepts and what its return type is (although the former can be omitted)) in other calling functions (such as in main).
As mentioned by another answer, the compiler will compile your program from top to bottom. Thus, when it reaches a given line in your program where you use your function, if you had not previously declared it, it would not know how to parse and compile that statement, and/or be able to detect if it consists of an error.
Take a simple example:
void square(int*);
int main(void) {
int number = 4;
number = square(number); // ERROR
// correct usage would be:
square(&number);
return 0;
}
void square(int *num) {
if (!num)
return;
*num *= *num;
}
However, if you had not declared square before main, the compiler would have no way of knowing what do with your call to square inside main, or which of the two calls was an error.
In other words, square is an undeclared identifier if you have not declared the function before calling it.
Just like you cannot do something like:
int main(void) {
int x = 2;
y = x + 5; // ERROR: undeclared identifier 'y'
int y;
return 0;
}
... because the compiler has no idea what y is by the time it reaches its first usage.
When I learned C using Microsoft Visual Studio, it didn't allow me to create an array with a non-constant size. I had to either put a value like int arr[5]; or do #define size 5 and do int arr[size];. However today using Clion, I noticed it allows me to do the following:
#include <stdio.h>
int main()
{
printf("Enter a value: ");
int x;
scanf("%d", &x);
int arr2[x];
for (int i = 0; i < x; i++)
{
arr2[i] = i;
printf("Array at %d is %d.\n", i, arr2[i]);
}
return 0;
}
This C code compiles and runs without any problems -- no segment fault or anything. What's going on? Is this legal C code and I just learned in an IDE that didn't allow it, or is this invalid C code and I'm just using a bad compiler? On my other computer which is using Linux, I even installed GCC 7.2 and the same syntax is allowed. I don't understand. Is this a CLion issue, CMake issue, or a C lang issue?
My compiler and CMake are listed below. Thanks.
This is valid C. It is referred to as a variable length array (VLA). This feature was added to the language as part of the C99 standard.
MSVC is well known for not supporting many C99 and later features, including VLAs.
I am new with c and I'm trying to use doubles variable. Unfortunately, the compiler (Code::Blocks) seems to ignore absolutely what i'm writing.
#include<stdio.h>
int main()
{
double x=1.03;
printf("x: %lf",x);
return 0;
}
and the output is:
x: 0.000000
what is the problem?
Use %f instead of %lf. Doubles only need %f; see the "specifiers" table here.
If printf is looking for a larger value than you are providing, what prints out will be affected by what happens to be in memory near the x argument that you provided. In this case, I'm guessing that's 0.
Edit: Thanks to #Olaf for pointing out that the specification says %lf should work just fine. Apparently the OP's compiler or compiler version is nonstandard. Alternatively, perhaps the project settings are selecting nonstandard compiler behaviour. (I suppose the compiler or library implementation of printf could be buggy, as well.)
I've got a function that takes a matrix of velocities for a bunch of particles and tries to calculate the total kinetic energy of the particles.
It doesn't give me the right value. In order to debug, I added a few printf("value: %e \n", energy) in the function.
And now, the return value depends on how many of these printfs I leave uncommented.
double GetKineticEnergy(int dim, int nParticles, double vel[nParticles][dim], double mass)
{
int i,j;
double sum;
double energy = 0;
for(i=0;i<nParticles;i++) {
sum = 0;
for(j=0;j<dim;j++) {
sum += vel[i][j]*vel[i][j];
}
energy += sum*mass/2;
// printf("energy: %e \n", energy);
}
// printf("total: %e \n", energy);
return(energy);
}
and right after returning to the caller I print the returned value. I get 18.0, 19.0, 21.0, or 24.0, depending on which combination of the printfs I uncomment.
What am I doing wrong?
Update:
In trying to troubleshoot this, I've commented out pretty much everything. The function is reduced to
{
double energy = 123;
return(energy);
}
and the main program is
int main() {
double a;
double vel[5][5];
a = GetKineticEnergy(1, 1, vel, 1);
printf("value: %e \n", a);
}
and I get
value: 0.000000e+00
as output.
Update:
The problem goes away if I hardcode the second dimension of the 2D array double vel[][3]. For the time being, this seems like a useful fix, but I cringe at that type of hardcoding.
It can happen if GetKineticEnergy function is in a different file and prototype is not available. Consider declaring its prototype in main or include required header file.
You have invoked undefined behaviour.
When you are faced with seemingly inexplicable behaviour from a C program, it is typically the result of undefined behaviour. Here are a few potential problems that you should look into:
Compiler warnings
Compilers usually omit many important warning messages by default, and you have to enable those yourself. Compiling with optimizations enabled can also activate some additional warning messages due to the added code analysis. If you're using GCC, you should at a minimum use something like gcc -ansi -pedantic -W -Wall -O2.
Function prototypes
Have you provided correct function declarations (with prototypes) for all the functions in your code? Without a correct declaration of GetKineticEnergy(), the compiler will pass the last argument as int and assume that the return type is int.
Did you #include <stdio.h>? printf() is a variadic function. Variadic functions usually require different calling conventions than normal functions. Calling a variadic function without the correct prototype causes undefined behaviour.
Buffer overflow
Did you allocate enough memory, or specify a large enough size, for the array passed to the function? Are you passing the correct dimensions? Accessing elements beyond the limits of a buffer can cause perplexing results, especially with optimizations enabled.
I am using Code Block with GNU GCC Compiler. And I am trying this code
int number,temp;
printf("Enter a number :");
scanf("%d",&number);
temp = sqrt(number);
printf("\n%d",sqrt(number)); //print 987388755 -- > wrong result
printf("\n%d",temp); //print 3 -- > write result
return 0;
and in this code there are a result for input value 10 is
987388755
3
what is wrong in this code?
sqrt returns a double:
double sqrt(double x);
You need:
printf("\n%g",sqrt(number));
Using incorrect format specifier in printf() invokes Undefined Behaviour. sqrt() returns double but you use %d.
Change:
printf("\n%d",sqrt(number));
to:
printf("\n%g",sqrt(number));
Note that sqrt() returns a double, not an int - your compiler should be warning you about this, so long as you have warnings enabled. e.g. gcc -Wall ... (and if you don't have warnings enabled, then it's time to start making a habit of it).