3

Let us say i have

File1.c:

#include<stdio.h>
#include"File2.c"

void test(void)
{
sum(1,2);
}

int main(void)
{
int sum(int a,int b);
test();
sum(10,20);
return 0;
}

File2.c:

int sum(int x,int y)
{
printf("\nThe Sum is %d",x+y);
}

Now as far as my understanding goes test() calling sum() should give a Compile-Time Error since i have made/declared sum() local to main, which i am not getting, and the program is running fine without any errors.

My main purpose is to define sum in File2.c and make it local to main() so that no other function has visibility to this function sum().

Where am i going wrong?

underscore_d
  • 6,309
  • 3
  • 38
  • 64
Sadique
  • 22,572
  • 7
  • 65
  • 91
  • There's an implicit `extern` in front of the declaration of `sum()` inside `main()`. With your code as written, `test()` 'sees' the definition of `test()` because it appears in the translation unit before `test()` does. If only `main()` is to see `sum()` then one file must contain `main()` and `static int sum(...){...}`. – Jonathan Leffler Sep 05 '10 at 16:57
  • Why do you want to make the `sum` function visible only for `main`, if you're calling it from `test, too`? Are you planning to have 2 `sum` functions (with different purposes)? – Cristian Ciupitu Sep 05 '10 at 17:07
  • @Cristian Ciupitu: Xaero doesn't want to call `sum` from `test`; it's just an example to show that it's not giving a compilation error. – jamesdlin Sep 05 '10 at 18:24
  • 1
    In C (unlike C++): does not require functions to be declared before use. The compiler will happy to generate the appropriate function call stuff then the linker will link resolve the names latter. Note if in test() you do **sum( 1.2 , 2.4)** you will get very funky results as the compiler will push doubles onto the stack (not integers) and yet the linker will still correctly link the code. If you performed sum( 1.2, 2.4) in main() then the doubles will be converted into ints before being pushed to the stack (as the main function knows that sum() is expecting integers). – Martin York Sep 05 '10 at 19:57

3 Answers3

7
  1. Mark the function as static (this makes it local to the current translation unit).

  2. For the love of god, do not include .c files! (read me)

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • 1
    Just marking the function `static` won't help unless Xaero also changes which files contain the definitions of `sum` and `test`. – jamesdlin Sep 05 '10 at 18:25
5

Prototypes are helpful when compiling as they tell the compiler what a function's signature is. They are not a means of access control, though.

What you want to do is put sum() into the same source file as main() and give it static linkage. Declaring it static means it will only be available in that one .c file, so functions in other source files will be unable to call it.

Then move test() to another source file. That'll let main() call test() but not let test() call sum() since it's now in a different source file.

File1.c

#include <stdio.h>

/* NO! Do not #include source files. Only header files! */
/*** #include "File2.c" ***/

/* Prototypes to declare these functions. */
static int sum(int a, int b);
void test(void);

int main(void)
{
    test();
    sum(10, 20);
    return 0;
}

/* "static" means this function is visible only in File1.c. No other .c file can
 * call sum(). */
static int sum(int x, int y)
{
    printf("\nThe Sum is %d", x + y);
}

File2.c

void test(void)
{
    /* Error: sum() is not available here. */
    sum(1, 2);
}

Notice, by the way, that I commented out the line #include "File2.c". You should never use #include for .c source files, only for .h header files. Instead you will be compiling the two source files separately and then linking them together to make the final program.

How to do that depends on your compiler. If you're using an IDE like Visual C++ on Windows then add the two source files to a project and it will take care of linking them together. On Linux you'd compile them with something like:

$ gcc -o test File1.c File2.c
$ ./test
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • Shouldn't the prototype have static in front as well like this? static int sum(int a, int b); – Sadique Sep 05 '10 at 17:23
  • `static` only has meaning at the implementation of the function. Prototypes are never externally visible (i.e. visible to other .c files), they only tell the compiler "When you are ready to link together an executable, a function called sum that looks like this will be available." – Clueless Sep 05 '10 at 18:44
  • 1
    Xaero is correct; Clueless is, well, clueless. It's invalid (the compiler should issue a diagnostic message) to omit `static` in the prototype if the function will later be defined `static`. – R.. GitHub STOP HELPING ICE Sep 05 '10 at 19:56
  • To be pedantic, it's valid to omit `static` in *subsequent* prototypes, if they otherwise match an earlier prototype that *did* include it. However, that seems horribly and pointlessly brittle to me. So, broadly, R is correct. See this question (which, although ostensibly asked for C, was answered for C++...): https://stackoverflow.com/questions/5261299/static-keyword-in-function-declaration-can-be-missing-in-function-definition – underscore_d Nov 18 '18 at 09:57
1

You have included File2.c in File1.c, so the sum function is defined in File1.c. Remove that line and things should work (you will have to #include <stdio.h> in File2.c).

Note that most compilers will accept an implicit definition of the sum() function as used in test() unless they are in strict mode. For example, calling gcc File1.c File2.c will succeed with no errors. If you want to see all the warnings available, call gcc -Wall -pedantic File1.c File2.c which will warn you that sum is implicitly defined in test() and that your implementation of sum() doesn't return an int. Even then it will compile successfully and run.

Clueless
  • 3,984
  • 1
  • 20
  • 27