File included problems

S

Stoneforever

Hi, I got a problem, I have three files, for example:

/****a.h*******/
#define X1 10
#define X2 10
......................

/****b.c*******/
#include "a.h"
int add(int x,int y)
{
return x+y;
}

/****c.c*******/
#include "a.h"
void main()
{
int x,y;
x = y = 10;
add(x,y);
}

why the compiler give me the error: undefined reference to 'add', the
compiler i used is Dev-C++.
thanks, any help will be appreciated.
wangshi
 
I

Ian Collins

Stoneforever said:
Hi, I got a problem, I have three files, for example:

/****a.h*******/
#define X1 10
#define X2 10

You require a prototype for add in here:

extern int add(int x,int y);
......................

/****b.c*******/
#include "a.h"
int add(int x,int y)
{
return x+y;
}

/****c.c*******/
#include "a.h"
void main()

int main(void)
 
F

Flash Gordon

Ian said:
Stoneforever wrote:

In addition to what Ian said you need to find out how to get Dec-C++ to
compile and link together both C files. How to do that is implementation
dependant, so you need to read the documentation for Dev-C++ and if you
require further help ask on a group or mailing list for Dec-C++. We
don't deal with how to drive every single tool set under the sun here.
 
B

Bill Pursell

Stoneforever said:
Hi, I got a problem, I have three files, for example:

/****a.h*******/
#define X1 10
#define X2 10
.....................

/****b.c*******/
#include "a.h"
int add(int x,int y)
{
return x+y;
}

/****c.c*******/
#include "a.h"
void main()
{
int x,y;
x = y = 10;
add(x,y);
}

why the compiler give me the error: undefined reference to 'add', the
compiler i used is Dev-C++.
thanks, any help will be appreciated.


It depends on how you are trying to compile. I don't
know anything about Dev-C++, but here are 3 attempts
to compile with gcc, the first fails, the second works but
is not generally the desirable approach, and the
third is...less incorrect. (I would prefer that the add
function be compiled into a seperate .a or .so rather
that just building an object file, but for something
this simple, that's overkill.)

$ cat a.h b.c c.c
/****a.h*******/
#define X1 10
#define X2 10
extern int add(int x,int y);


/****** b.c *****/
#include "a.h"
int add(int x,int y)
{
return x+y;
}


/****c.c*******/
#include <stdlib.h>
#include "a.h"
int main(void)
{
int x,y;
x = y = 10;
add(x,y);
return EXIT_SUCCESS;
}


$ gcc -Wall -pedantic c.c
ld: Undefined symbols:
_add

$ gcc -Wall -pedantic c.c b.c

$ gcc -c -Wall -pedantic -c b.c
$ gcc -c -Wall -pedantic -c c.c
$ gcc c.o b.o


To clarify further: the first attempt to build
an executable from c.c fails because the
linker cannot locate the code for the add
function. Notice that it does compile correctly,
but it fails to link. Building the executable
consists of several steps, of which compilation
is only one. Often, the word "compile" has
been incorrectly conflated with the attempt
to build an executable, and it is an unfortunate
twist of language. I generally would agree
that c.c "didn't compile", but in fact, it did
compile--but you didn't build an executable
because the link step failed.

The second attempt to build works because
I explicitly tell the compiler (really the compiler
tool chain!) that it should take code from both
b.c and c.c and build an executable.

The third attempt (the final three commands)
first builds an object file from b.c into a file
named b.o. It does't link, because I specified
-c on the command line (I have no idea
how to do that with your compiler). In other words,
the command "gcc -c b.c" doesn't attempt to build
an executable. It just builds object code. The next
command compiles the code in c.c and builds
c.o. The final command takes the code from b.o
and c.o and builds an executable from them, ensuring
that there is exactly one function named "main" and
making sure that all the functions referenced from
main are present.


Hope that didn't confuse you further....
 
P

pete

/****a.h*******/
#define X1 10
#define X2 10
.....................

/****b.c*******/
#include "a.h"
int add(int x,int y)
{
return x+y;
}

/****c.c*******/
#include "a.h"
void main()
{
int x,y;
x = y = 10;
add(x,y);
}

How to link c.c with b.c,
is according to the rules of your implementation.
The following, should not be too hard to compile:

/****a.h*******/
#define X1 10
#define X2 10

/****b.h*******/
int add(int x,int y);

/****b.c*******/
#include "b.h"

int add(int x,int y)
{
return x + y;
}

/****c.c*******/
#include "a.h"
#include "b.h"

int main(void)
{
int x, y;

x = y = X1;
add(x, y);
return 0;
}
 
J

Joe Wright

pete said:
How to link c.c with b.c,
is according to the rules of your implementation.
The following, should not be too hard to compile:

/****a.h*******/
#define X1 10
#define X2 10

/****b.h*******/
int add(int x,int y);

/****b.c*******/
#include "b.h"

int add(int x,int y)
{
return x + y;
}

/****c.c*******/
#include "a.h"
#include "b.h"

int main(void)
{
int x, y;

x = y = X1;
add(x, y);
return 0;
}
A little too busy. Consider..

/* a.h Everything we need to know */
#define X 10
int add(int x, int y);
/* end of a.h */

/* b.c doesn't need to know anything. */
int add(int a, int b)
{
return a + b;
}

/* c.c needs to know. */
#include <stdio.h>
#include "a.h"
int main(void)
{
int x, y, z;
y = z = X;
printf("%d\n", z);
x = add(y, z);
printf("%d\n", x);
return 0;
}

gcc -c b.c c.c
gcc -o c.exe c.o b.o
 
P

pete

Joe said:
A little too busy. Consider..

/* a.h Everything we need to know */
#define X 10
int add(int x, int y);
/* end of a.h */

/* b.c doesn't need to know anything. */
int add(int a, int b)
{
return a + b;
}

/* c.c needs to know. */
#include <stdio.h>
#include "a.h"
int main(void)
{
int x, y, z;
y = z = X;
printf("%d\n", z);
x = add(y, z);
printf("%d\n", x);
return 0;
}

It's more better style to have the header file that goes
with "b.c", to be named "b.h".
 
J

Joe Wright

pete said:
It's more better style to have the header file that goes
with "b.c", to be named "b.h".
That would be In Your Humble Opinion of course. Were it mine, and c.c
contains the main entry, I might have called it "c.h" instead. My point
is that if you write a modest C program with relatively few translation
units then one header will probably suffice for all the translation
units. All translation units may #include the header without problem
even if they don't use any of it. KIS.
 
Y

Yost

I have really tried to understand this, but I am at a loss.

I have simplifed my code a lot here, to just the elements that are
relevent, but I still don't see what is happening.

As you can see from the main(), I'm trying to ultimately end up with an
array of VideoInfo structures, and the number of items in the array.

Everything works up through the CreateNewElement function, where it does
create the new element, and I can break at the end of that function, and
see the data in the element, and everything looks alright. When I
return from the function though, in CreateNewArray, I can't see the data
in the new element. And of course, when the whole thing returns, I
can't see any of it. The memory has all been allocated, but I can't
seem to get to it.

Also, in my main() program, any attempt to get to use one of the
elements in the array gives me a compiler error of "Unknown size", hence
the commented out function.

I tried to not do anything fancy in the code, but I seem to be missing
something really basic here. I would love to understand what I'm doing
wrong. Any help is appreciated.



// allocates a new element and copies data from old_data into
// the element
int CreateNewElement( VideoInfo *newElement, void *old_data )
{
newElement = (VideoInfo*)malloc( sizeof(VideoInfo) );
if(newElement) {
// copy data from the data to the element
}

return 0;
}


// allocates a new array, and handles filling the array with data
int CreateNewArray( VideoInfo **array, int *arrayLen )
{
VideoInfo *newMetaArray = NULL;

// here I get the number of elements from another list of data
newVideoInfo = (VideoInfo*)malloc( numElements * sizeof(VideoInfo*) );

// here I copy data from that other list into each element of mine
for(int i = 0; i < numElements; i++) {
CreateNewElement( &array, old_list );
}

// handle the returns
*arrayLen = numElements;
*array = newVideoInfo;

return 0;
}


int main()
{
VideoInfo *MasterArray = NULL;
int MasterArraySize = 0;

CreateNewArray( &MasterArray, &MasterArraySize );

for( int i = 0; i < MasterArraySize; i++ ) {
// do something with each element

// DoFunction( &MasterArray );
}
}
 
C

CBFalconer

Yost said:
I have really tried to understand this, but I am at a loss.

I have simplifed my code a lot here, to just the elements that are
relevent, but I still don't see what is happening.

As you can see from the main(), I'm trying to ultimately end up
with an array of VideoInfo structures, and the number of items in
the array.

Everything works up through the CreateNewElement function, where
it does create the new element, and I can break at the end of that
function, and see the data in the element, and everything looks
alright. When I return from the function though, in
CreateNewArray, I can't see the data in the new element. And of
course, when the whole thing returns, I can't see any of it. The
memory has all been allocated, but I can't seem to get to it.
.... snip ...

// allocates a new element and copies data from old_data into
// the element
int CreateNewElement( VideoInfo *newElement, void *old_data )
{
newElement = (VideoInfo*)malloc( sizeof(VideoInfo) );
if(newElement) {
// copy data from the data to the element
}

return 0;
}

Of course. You discard the pointer to the new element when you
return. Try this function (and don't use // comments in Usenet,
they are subject to malwraps).

/* allocates a new element and copies data from old_data into
the element */
VideoInfo *CreateNewElement(void *old_data )
{
VideoInfo *newElement;

newElement = malloc(sizeof(*newElement));
if (newElement) {
/* copy data from the data to the element */
}
return newElement;
}

and NEVER cast the return value from malloc. You detect failure by
testing the return value.
 
J

J. J. Farrell

pete said:
It's more better style to have the header file that goes
with "b.c", to be named "b.h".

I can't imagine where you'd get such an idea, but I'd call it nonsense.
In my opinion and experience, it's generally better style to put
everything which is common to the whole program (or could reasonably be
expected to be) into a single header. Details depend on the size and
organization of the program, of course, but it's definitely not
"better" to have a header per .c file. I can think of many reasons to
arrange headers in many different ways depending on circumstances, but
a header per .c file is not one of those ways.
 
R

Richard Heathfield

J. J. Farrell said:

I can think of many reasons to
arrange headers in many different ways depending on circumstances, but
a header per .c file is not one of those ways.

My own preference is one header per module. A module may consist of more
than one C file. The header represents the public interface to the module,
which is implemented in one or more C files.
 
C

CBFalconer

J. J. Farrell said:
pete wrote:
.... snip ...

I can't imagine where you'd get such an idea, but I'd call it
nonsense. In my opinion and experience, it's generally better
style to put everything which is common to the whole program (or
could reasonably be expected to be) into a single header. Details
depend on the size and organization of the program, of course,
but it's definitely not "better" to have a header per .c file. I
can think of many reasons to arrange headers in many different
ways depending on circumstances, but a header per .c file is not
one of those ways.

What an ugly idea. A C file, properly described by a .h file, is
reusable unchanged in many situations. If it uses another .c file,
then its .h file should #include that files .h header.
 
S

Stoneforever

Thanks for everybody!
Using the extern int add(int x,int y) in a.h doesn't work, and i don't
know why.
The only thing i can do is to replace the "b.c" with "b.h".
Maybe it does depend on the implementation.



Ian Collins 写é“:
 
J

Jordan Abel

2006-11-06 said:
Thanks for everybody!
Using the extern int add(int x,int y) in a.h doesn't work, and i don't
know why.
The only thing i can do is to replace the "b.c" with "b.h".
Maybe it does depend on the implementation.

"undefined reference" in this case probably means you're not linking the
two object files together.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,197
Latest member
ScottChare

Latest Threads

Top