Multiple defenitions of function - c

I'm making a program that has 3 files: 2.c, 2tele.c, tele.h
2.c
#include <stdio.h>
#include <stdlib.h>
#include "2tele.c"
int main(void){
TELEFONE tf = preenche_telefone(tf.numero, tf.nome);
mostra_telefone(tf);
}
2tele.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tele.h"
void mostra_telefone(TELEFONE tf){
printf("\nNumero = %d\nNome = %s", tf.numero, tf.nome);
}
TELEFONE preenche_telefone(char nome[], int numero){
TELEFONE tf;
printf("Introduza o numero\n");
scanf("%d", numero);
tf.numero = numero;
printf("Introduza o nome\n");
scanf("%s", nome);
strcpy(tf.nome,nome);
return tf;
}
tele.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct contacto{
int numero;
char nome[100];
}TELEFONE;
void mostra_telefone(TELEFONE tf);
In line 6 of 2tele.c I'm getting the error multiple definition of 'mostra_telefone', however I have read other posts and have also defined it on tele.h.
What should I do?
Edit: When i include "tele.h" instead of "2tele.c" it says that "TELEFONE tf = preenche_telefone(tf.numero, tf.nome);" has a bad initializer

In line 6 of 2tele.c I'm getting the error multiple definition of 'mostra_telefone',
That's a misleading claim. You might get such a message when you attempt to link the program, but that would be a function of the details of your build procedure. You appear to have cherry-picked a detail of the diagnostic that does not convey the nature of the problem. Always give us an exact copy of the full diagnostic message.
however I have read other posts and have also defined it on tele.h.
No, you haven't. You have declared it in tele.h, which is in fact exactly what you should do. And every source file that references that function should #include the header, to get only a declaration, and avoid #includeing 2tele.c, which would provide a[n additional] definition. For functions, the difference is that a definition includes the function body.
Including the .c file instead of the .h file means that 2.c provides a definition of mostra_telefone(). If you compile 2.c to create an object file and also compile 2tele.c to create an object file, or if you compile both together to build a program directly, then each one provides a definition. It does not matter that the two definitions are lexically identical, or that they ultimately are derived from the same source file. There can be multiple declarations of the function, in the same or different translation units, but in the whole program, as compiled, there can be only one definition.
Solution: no file #includes 2tele.c. All that want to access the functions defined within instead declare those functions before use without defining them (except 2tele.c itself). The conventional way to do this is to #include a header containing the needed declarations -- in your case, that's tele.h.
But you say,
When i include "tele.h" instead of "2tele.c" it says that "TELEFONE tf = preenche_telefone(tf.numero, tf.nome);" has a bad initializer
Turn up your compiler's warning level. With gcc and other compilers that understand its options, for example, turn on at least -Wall. That should clue you in to the root of this problem:
2.c: In function ‘main’:
2.c:6:5: warning: implicit declaration of function ‘preenche_telefone’ [-Wimplicit-function-declaration]
TELEFONE tf = preenche_telefone(tf.numero, tf.nome);
That arises because there is no declaration of preenche_telefone() in tele.h. It is an error for main() to attempt to call that function without an in-scope declaration for it, but for historical reasons, many compilers accept the call and try to guess a declaration. That guess will invariably assume that the function's return type is int, and an int is not a valid initializer for a struct such as your TELEFONE.
Solution: Add the needed declaration of preenche_telefone() to tele.h.

Related

Correct use of extern when using global variables imported from standard library?

I am trying to learn the use of the extern keyword. As an example I am using the getopt C library function. From my understanding of the extern keyword, it used to indicate to the compiler that a certain variable that has been defined in another file is going to be used. So whenever I am going to be using the getopt variables like opterr, optind, etc, should I(would it be wrong of me to) do this:
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
extern int optopt;
extern int opterr;
extern int optind;
extern char *optarg;
int main(int argc, char **argv) {
/* code using getopt */
}
When I looked at the manpage for getopt(3), I saw these declarations already mentioned under #include <unistd.h>. So I thought that these were declared in that header file but when I looked into the header file itself, there was no such declaration.
So my question is: is there anything wrong with using these statements at the beginning even if for the sake of improving readability for someone who doesn't how getopt works. Also, at the end of the day if the linker is going to resolve references, anyways, is there any reason to use extern at all?
Also, at the end of the day if the linker is going to resolve references, anyways, is there any reason to use extern at all?
The extern keyword can tell the compiler that an unknown symbol is going to be provided by another file.
Consider the situation where we have file1.c with:
int myvariable;
And file2.c with:
#include <stdio.h>
int main() {
myvariable = 10;
printf("myvariable is %d\n", myvariable);
return 0;
}
Attempting to compile this will fail with:
file2.c: In function ‘main’:
file2.c:4:5: error: ‘myvariable’ undeclared (first use in this function)
4 | myvariable=10;
Adding the appropriate extern declaration to file2.c allows us to compile it without errors:
#include <stdio.h>
extern int myvariable;
int main() {
myvariable = 10;
printf("myvariable is %d\n", myvariable);
return 0;
}
Header files can be nested.
unitstd.h includes many other files, the specific declarations you are looking for are in getopt.h,
These statements do not improve readability, they decrease it by adding duplicate garbage code.
A programmer familiar with C but not with getopt function would think these are your custom variables, not part of the standard library, because nothing in the standard library should be redeclared.
The linker is the last step in building the executable.
The external keyword is for the compiler to know the names and types, so it can build code with references for the linker to resolve later.
While it's OK to have more than one declaration for a function or object, as a rule it's best not to redeclare anything declared in a standard library header. It might cause issues if what you declared doesn't exactly match what's in the headers.
Also, just because the man pages say to include unistd.h doesn't necessarily mean the declaration is in that specific file. The declaration in question could be in a file that unistd.h includes. All it means is that including unistd.h will give you the required declaration.

Why are function definitions implicitly external in C?

I read that the extern keyword is implicit in the context of functions, so unless you specify otherwise using the static keyword (which if I'm not mistaken is basically a completely separate concept from the static that variables employ—they just share a keyword), they are visible to all object files. This makes sense; having the declarations be implicitly external, while technically unnecessary when the declarations are in the same file as the definition, is useful because the programmer doesn't have to type extern every time they want to use a function out of its defining file, which is more often the case than not. What seems odd to me is that it is implicit for the declarations and the definition.
With a variable, I don't need to include an extern for the definition, and in fact, while I can do this without error, my compiler gives me a warning for it.
For example, I can have mylib.h:
int var = 5;
//it isn't necessary to write this as
//extern int var = 5;
//my compiler even warns against it
and test.c
#include "mylib.h"
extern int var;
I would normally assume the implicit extern for functions to be the same, that is, if I defined int func(int par) in mylib.h, there would not be an implicit extern before it, but there would be an implicit extern for any declaration of it (such as if I declared it for use in test.c).
It also doesn't make much sense from the perspective of the extern keyword being used as a way of telling the compiler to look elsewhere for the definition, when the definition would never be external of the file it is in.
I feel like I'm missing something here.
If you use int x = 10; in any header file, then you are entering into trouble, because if you include the same header file in any other file (.c or .h) that is linked with test.c then you will get an error redefinition of variable x.
You can try that for yourself.
So always keep extern int x; in a header file,
and define it int x = 10; in any .c file.
So, in this case, if you include the header file in multiple places, it is fine, because the header file only has a declaration and you can declare the same variable in multiple places without any problem.
you can try this sample program to test the error multiple definition of `global_value'
test.h
extern int global_value;
test.c
#include <stdio.h>
#include "test.h"
int global_value = 10;
int test_func()
{
printf("golbal_value = %d", global_value);
global_value = 20; // changed here, reflect in main after test_func call
}
main.c
#include <stdio.h>
#include "test.h"
int main()
{
test_func();
printf("global_value = %d\n", global_value);
return 0;
}
the above program works perfectly. to get the error bring that extern int global_value; to test.c and int global_value = 10; to test.h and compile all together gcc test.c main.c

Using functions with two seperate files

Files: A(main), B
I have learned that B's function can't be use in A without
funcntion definitions.
But my code ran normally with A, B files without function definitions
This is my code:
B.c
void a()
{
printf("hi");
}
A.c
#include <stdio.h>
void main()
{
a();
}
What is it? I'm confused.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
addendum...
sorry for my bad question.
my code works well with error.
but i couldn't see error.
but i have more question for difference between
'void a();'
'extern void a();'
Once upon a time, C did not require prior declaration of all functions. Many compilers still let you get away with this.
In file A.c, when you called
a();
where a was a function the compiler has never seen before, the compiler assumed that the declaration
extern int a();
was in scope. That is, the compiler assumed that a was a function taking unspecified arguments and returning int.
Or, that used to be the rule. That rule is no longer in C, so yes, you are supposed to explicitly declare all your functions before you call them. Most of today's compilers will warn you when they apply the old rule, and many aren't willing to apply the rule at all, or at least, not unless you use a non-default option flag requesting them to. But it sounds like your compiler is still willing to apply the rule without warning or error. That's great if you're compiling a bunch of very old code, but it's not so great if you're trying to learn modern C.
Now, in this case you have the additional problem that the actual definition of function a in file B.c defines it as returning void, not int, so theoretically that's wrong, too. But, in practice, the error of misdeclaring (or mis-calling) void- versus int-returning functions is an innocuous one, that doesn't cause any real problems. (It's still wrong, though, and worth avoiding.)
I think you know this, but a correct setup would either be to have file A.c look like this:
#include <stdio.h>
extern void a(void);
int main()
{
a();
}
or else to create the file B.h containing
extern void a(void);
and then to have file A.c look like this:
#include <stdio.h>
#include "B.h"
int main()
{
a();
}
(Note that I have also changed void main() to int main(), for correctness. If you're using an old compiler, as it sounds like you are, you may also have to add the line return 0; at the end of main().)
Addendum. You had also asked about that extern keyword. It has to do with the distinction between declarations and definitions. But this distinction plays out slightly differently for functions, versus global variables.
Declarations explain what type something has. Definitions explain what type something has, and they additionally allocate memory for the something, and supply its initial value.
These are declarations:
extern int i;
int f(int);
extern int f2(int, double);
These are definitions:
int i;
int i2 = 2;
int f(int x) { return 2 * x; }
int f2(int n, double x) { return n * x; }
The keyword extern explicitly says, "This is a declaration, the definition is somewhere else." For global variables, this makes a big difference. But for functions, when you say int f(int);, the compiler can tell, when it finds a , instead of a {, that this is a declaration (not a definition), so the keyword extern is optional in function declarations.
(Also, functions are always global in C; there are no local functions.)
See also section 4.2 and section 4.3 of these course notes.

Is "small" a keyword in c?

This is the first code
#include <stdio.h>
#include <conio.h>
int main()
{
int small;//showing error-(two or more data type in declaration specifiers
}
This is the second code
#include <stdio.h>
int main()
{
int small;//normal declaration without any error
}
Whenever I include header file <conio.h> then declaring a identifier "small" gives an error, why?
I am using mingw gcc compiler and codeblocks ide
Also I have added following code in <conio.h>
#include <windows.h>
void gotoxy(short int col,short int row)
{
HANDLE hStdout=GetStdHandle(STD_OUTPUT_HANDLE);
COORD position={col,row};
SetConsoleCursorPosition(hStdout,position);
}
after removing above code from <conio.h>
int small;
works even after including <conio.h>.
I guarantee that small is not a keyword in C. If it were, the presence or absence of a #include directive would not make any difference.
The problem is that <windows.h> stupidly defines small as a macro. (Other answers and comments suggest it might be a typedef, but that wouldn't explain the problem you're seeing.)
I'm able to reproduce the problem on my system (Cygwin, Windows 7, compiling with mingw32-gcc, which is installed as part of the Cygwin package). Presumably the same thing would happen with MinGW installed separately from Cygwin.
First of all, <conio.h> is a (non-standard) header provided by the implementation. You almost certainly shouldn't be trying to modify it. You definitely shouldn't be adding a function definition to a header file (function definitions belong in .c files, not in .h files). If you want to write your own gotoxy function, declare it in your own header and define it in your own .c file; don't mess around with the implementation. (B
But when you added your gotoxy function to <conio.h>, you also added
#include <windows.h>
Here's a small program that illustrates the problem:
#include <windows.h>
int main()
{
int small;
}
When I compile this with mingw32-gcc, I get:
c.c: In function 'main':
c.c:4:9: error: two or more data types in declaration specifiers
c.c:4:5: warning: useless type name in empty declaration [enabled by default]
Digging further, it turns out that <windows.h> includes <rpcndr.h>, which contains the following:
#define small char
So every occurrence of the identifier small in any C source that has #include <windows.h> will be replaced by the keyword char -- which, in your case, will cause a syntax error.
A handy way to find things like this: gcc has a -E option that causes it to show the output of the compiler's preprocessor phase. With the above program, I tried this:
$ mingw32-gcc -E c.c | tail
#pragma pack(pop)
# 115 "c:\\gnustep\\bin\\../lib/gcc/mingw32/4.6.1/../../../../include/windows.h" 2 3
# 2 "c.c" 2
int main()
{
int char;
}
$
which shows how the int short; declaration was mangled by the preprocessor.
To be clear, this is entirely the fault of the maintainers of <windows.h> and <rpcndr.h>. small is a perfectly valid C identifier, and a system header absolutely should not define it as a macro. typedef char small; would have served the same purpose and not caused this problem. Others have had similar problems with <windows.h> defining macros min and max. That can be worked around with:
#define NOMINMAX
#include <windows.h>
but as far as I can tell there's no such workaround for small.
Incidentally, rpcndr.h also defines hyper.
The simplest solution is to call your variable something other than small -- and hope you don't collide with other macros defined in <windows.h>. Or you can add
#undef small
before the declaration. You shouldn't need to do either of these things, but thanks to poorly written system headers, such workaround are sometimes necessary.
Or just avoid including <windows.h> (that's not always possible).
(You could modify your copy of the rpcndr.h file, but I advise against doing so; it's likely to cause other problems, and your code still won't compile on a system where rpcndr.h hasn't been hacked.)
UPDATE : This may have been corrected. I don't see the error using x86_64-w64-mingw32-gcc under Cygwin on Windows 10. Perhaps someone else who uses mingw can investigate further.
No. There is no keyword like small in standard C. This may be a macro in <conio.h>.
C11: 6.4.1 Keywords:
keyword: one of
auto
break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
inline
int
long
register
restrict
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while
_Alignas
_Alignof
_Atomic
_Bool
_Complex
_Generic
_Imaginary
_Noreturn
_Static_assert
_Thread_local
I found it...
its a macro defined in some header file which is included in windows.h.
as i have included windows.h in conio.h so in my program it is automatically included when i include conio.h.
I Found it by ctrl + clicking on small
By adding #include <windows.h>, you are pulling in a lot of other header files. One problem that has been reported is of it defining a preprocessor macro "small". It has also been discussed in another SO question.
One workaround is to add #undef small after you #include <windows.h>.
Just define WIN32_LEAN_AND_MEAN macro in code or VS Properties dialog and the problem will be gone:
#define WIN32_LEAN_AND_MEAN
The error seems to be the fault of MinGW. The same error appears with large.
There is no such keyword, but check if it is typedefed somewhere.

Why is use of an array defined in File1 working in File2 (only declared there),even without "extern"?

Here I have two files externdemo1.c and externdemo2.c.In the first file,I have declared and initialized a character array arr at file scope.But I have declared it in the second file externdemo2.c without the extern keyword and made use of it there in the function display(). Here are my confusions arising from it.Please answer these three:
//File No.1--externdemo1.c
#include<stdio.h>
#include "externdemo2.c"
extern int display();
char arr[3]={'3','4','7'};
//extern char arr[3]={'3','4','7'};
//extern int main()
int main()
{
printf("%d",display());
}
//File No.2--externdemo2.c
char arr[3];
int display()
{
return sizeof(arr);
}
1) Why does the program compile fine even though I have declared arr without the extern keyword in externdemo2.c?I had read that the default linkage of functions is external,but I am not sure if that's so even for variables.I only know that global variables have extern storage class.
2) What is the rigorous difference between extern storage class and extern linkage.I badly need a clarification about this.In the first file,where I have defined the array arr,I haven't used the keyword extern, but I know that it has extern storage class by default.But in the second file, isn't there any default extern ,storage class or linkage,about the global variable arr,ie, in externdemo2.c?
3) Check the commented out line in the first file externdemo1.c.Just to test it, I had used the line extern char arr[3]={'3','4','7'};.But it gives the error 'arr' initialized and declared 'extern'.What does this error mean? I have also mentioned a commented line extern int main(),but it works fine without error or warning.So why can we use extern for a function even though a function is extern by default,but not for a variable,like arr here?
Please take some time to bail me out over this.It will clear most of my lingering doubts about the whole extern thing.It will be immense help if you can answer all 3 bits 1),2) and 3). Especially 3) is eating my brains out
Main questions
Basically, because you've included the source of externdemo2.c in the file externdemo1.c.
This is the big question. Because there is no initializer, the line char arr[3]; in externdemo2.c generates a tentative definition of the array arr. When the actual definition with initialization is encountered, the tentative definition is no longer tentative — but neither is it a duplicate definition.
Regarding extern storage class vs extern linkage...Linkage refers to whether a symbol can be seen from outside the source file in which it is defined. A symbol with extern linkage can be accessed by name by other source files in which it is appropriately declared. To the extent it is defined, extern storage class means 'stored outside of the scope of a function', so independent of any function. The variable defined with exern storage class might or might not have extern linkage.
Because it is not defined with the keyword static, the array arr has extern linkage; it is a global variable.
With the commented out line uncommented out, you have two definitions of one array, which is not allowed.
I observe that you must be compiling just externdemo1.c to create a program — the compiler is including the code from externdemo2.c because it is directly included. You can create an object file from externdemo2.c. However, you cannot create a program by linking the object files from both externdemo1.c and externdemo2.c because that would lead to multiple definitions of the function display().
Auxilliary questions
I have placed both files in the [same directory]. If I don't include the second file in the first, then when I compile the first file it gives the error undefined reference to display. Since I have used extern for that function in the first file, isn't the linker supposed to link to it even if I don't include the second file? Or the linker looks for it only in default folders?
There are a couple of confusions here. Let's try dealing with them one at a time.
Linking
The linker (usually launched by the compiler) will link the object files and libraries that are specified on its command line. If you want two object files, call them externdemo1.obj and externdemo2.obj, linked together, you must tell the linker (via the build system in the IDE) that it needs to process both object files — as well as any libraries that it doesn't pick up by default. (The Standard C library, plus the platform-specific extensions, are normally picked up automatically, unless you go out of your way to stop that happening.)
The linker is not obliged to spend any time looking for stray object files that might satisfy references; indeed, it is expected to link only those object files and libraries that it is told to link and not add others at its whim. There are some caveats about libraries (the linker might add some libraries not mentioned on the command line if one of the libraries it is told to link with has references built into it to other libraries), but the linker doesn't add extra object files to the mix.
C++ with template instantiation might be argued to be a bit different, but it is actually following much the same rules.
Source code
You should have a header, externdemo.h, that contains:
#ifndef EXTERNDEMO_H_INCLUDED
#define EXTERNDEMO_H_INCLUDED
extern int display(void);
extern char arr[3]; // Or extern char arr[]; -- but NOT extern char *arr;
#endif /* EXTERNDEMO_H_INCLUDED */
You should then modify the source files to include the header:
//File No.1--externdemo1.c
#include <stdio.h>
#include "externdemo.h"
char arr[3] = { '3', '4', '7' };
int main(void)
{
printf("%d\n", display());
return 0;
}
and:
//File No.2--externdemo2.c
#include "externdemo.h"
int display(void)
{
return sizeof(arr);
}
The only tricky issue here is 'does externdemo2.c really know the size of arr?' The answer is 'Yes' (at least using GCC 4.7.1 on Mac OS X 10.8.3). However, if the extern declaration in the header did not include the size (extern char arr[];), you would get compilation errors such as:
externdemo2.c: In function ‘display’:
externdemo2.c:7:18: error: invalid application of ‘sizeof’ to incomplete type ‘char[]’
externdemo2.c:8:1: warning: control reaches end of non-void function [-Wreturn-type]
Your program looks a bit err. To me the #include "externdemo2.c" line appears invalid.
Following is the correction I have made and it works.
//File No.1--externdemo1.c
#include <stdio.h>
extern char arr[3];
extern int display();
int main()
{
printf("%d", arr[0]);
printf("%d",display());
}
//File No.2--externdemo2.c
char arr[3]={'3','4','7'};
int display()
{
return sizeof(arr);
}
Please follow the below links for better understanding:
Effects of the extern keyword on C functions
How do I use extern to share variables between source files?
Using #include as shown will make both as one file only. You can check the intermediate file with flag -E, as in:
gcc -E externdemo1.c

Resources