Linux Format forums Forum Index Linux Format forums
Help, discussion, magazine feedback and more
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

C Structure multiple files

 
Post new topic   Reply to topic    Linux Format forums Forum Index -> Programming
View previous topic :: View next topic  
Author Message
Crispy



Joined: Mon May 31, 2010 7:35 pm
Posts: 57

PostPosted: Wed Oct 31, 2012 12:58 pm    Post subject: C Structure multiple files Reply with quote

Hi,

I have been playing around a little bit with C but have come across a problem which I can't seem to get my head around. I have a main file which contains a structure:

main.c
Code:

#include <stdio.h>
#include <stdlib.h>

#include "test.h"

struct test
{
  int t1;
  int t2;
};

static struct test t;

int main( int argc, char **argv )
{
  int err = 0;
  t.t1 = 0;
  t.t2 = 0;

  err = test_struct_fnc( &t );

  printf("t.t1 = %d\n", t.t1);
  printf("t.t2 = %d\n", t.t2);

  return 0;
}


It includes the file test.h which simply contains a function prototype:

test.h
Code:

int test_struct_fnc( struct test *t__i );


This function is then found in test.c:

test.c
Code:


int test_struct_fnc( struct test *t__i )
{
  t__i->t1 = 10;
  t__i->t2 = 100;
}


which simply changes the values of t1 and t2 to 10 and 100 respectively. However, when I compile:

Code:

gcc -g -c test.c
gcc -g -c main.c
gcc -g -o test.exe test.o main.o


I get an error from test.c saying:

Code:

test.c:1: warning: ‘struct test’ declared inside parameter list
test.c:1: warning: its scope is only this definition or declaration, which is probably not what you want
test.c: In function ‘test_struct_fnc’:
test.c:3: error: dereferencing pointer to incomplete type
test.c:4: error: dereferencing pointer to incomplete type


I think this is because the structure test is declared in main not in test.c. However declaring the structure to be external - extern struct test; - in test.h doesn't work it still gives the same error.

I thought that perhaps changing struct test to typedef struct test would help, however I can't figure out how to share the type definition across the multiple files? I tried

Code:
 extern typedef test;


In the header file test.h however that gave an error saying it expected a ) before * token in test.c - which makes no sense to me. I just can't figure out what I'm supposed to do here so any help would be greatly appreciated.

Thanks in advance,
Chris
Back to top
View user's profile Send private message
Crispy



Joined: Mon May 31, 2010 7:35 pm
Posts: 57

PostPosted: Wed Oct 31, 2012 3:30 pm    Post subject: Reply with quote

I figured out a way around it, place all typedefs in a header file then include that header file in anything that requires those typedefs. For example:

typedefs.h
Code:

#ifndef TEST_H_FILE
#define TEST_H_FILE

typedef struct testy
{
  int t1;
  int t2;
} test;

#endif


The #ifndef directive is to prevent multiple definition as the file will be included in lots of different source files. I am curious as to whether there is another way to do it, anyone have any ideas?

Thanks,
Chris
Back to top
View user's profile Send private message
CJLL
LXF regular


Joined: Sat Jul 09, 2005 10:22 pm
Posts: 193

PostPosted: Sun Nov 11, 2012 5:09 pm    Post subject: Re: C Structure multiple files Reply with quote

Crispy wrote:
Hi,

Code:

int test_struct_fnc( struct test *t__i )



The keyword struct tells the compiler that you are defining a new data type, and shouldn't be used in a function parameter list. Rolling Eyes
_________________
--
The reward for self love is sticky hands
Back to top
View user's profile Send private message
einonm



Joined: Fri Apr 20, 2012 11:19 am
Posts: 29
Location: Cardiff, UK

PostPosted: Wed Nov 14, 2012 12:22 pm    Post subject: Reply with quote

Crispy wrote:
I figured out a way around it, place all typedefs in a header file then include that header file in anything that requires those typedefs.

The #ifndef directive is to prevent multiple definition as the file will be included in lots of different source files. I am curious as to whether there is another way to do it, anyone have any ideas?


Hi Chris,

You've discovered correctly that structures shared between many source files need to be placed in a header file and #included in those source files. This is the right thing to do.

A few other points are:

1. You don't need to typedef the struct, just putting the struct definition into the header file will be fine - and preferable, as it doesn't hide the fact that it's a struct (as opposed to an enum or int, for example).

2. If you #include the header file containing the struct definition, there is no need to declare it as extern, just use it. Try and avoid using extern if you can.
_________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." --Brian Kernighan
Back to top
View user's profile Send private message
einonm



Joined: Fri Apr 20, 2012 11:19 am
Posts: 29
Location: Cardiff, UK

PostPosted: Wed Nov 14, 2012 12:26 pm    Post subject: Re: C Structure multiple files Reply with quote

CJLL wrote:

The keyword struct tells the compiler that you are defining a new data type, and shouldn't be used in a function parameter list.


Yes, the compiler thinks that a new struct is being defined, only because it can't find the definition elsewhere. Putting the struct definition in the header file above the function declaration would solve this.

Using the keyword 'struct' in a function parameter list is the correct thing to do, the only way to get around this is to typedef the struct, which I wouldn't recommend doing - so the function declaration is all good, just missing the struct definition.
_________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." --Brian Kernighan
Back to top
View user's profile Send private message
Crispy



Joined: Mon May 31, 2010 7:35 pm
Posts: 57

PostPosted: Fri Feb 08, 2013 11:57 am    Post subject: Reply with quote

Thank you for your replies and my apologies for such a delayed response. Thank you as well for the tips Smile.

I have a couple of new questions if that's ok? If I used malloc to allocate some memory, is that memory contiguous? I think that's the right phrasing - i.e. each element of the array is next to each other? If so does that still hold for 2D arrays? If it isn't, would it be more efficient to make it contiguous?

My next question is a bit difficult to explain - lets assume I have 3 files. A main file, main.c, a header file which contains nothing but data, data.h - for example:
Code:
int p;
int *ptr;

and a file funcs.c which contains a function testfnc (also have funcs.h - only has function prototype). The main file includes data.h and funcs.h, however funcs.c only includes funcs.h. The function testfnc is then called from the main file. Is it more efficient to pass the integer p from data.h to the function testfnc as an argument or include the data.h file in funcs.c? I.e. from the main file: testfnc( p ); or testfnc();?

Finally, if the function testfnc has to allocate memory (using malloc or calloc), say a large array, and the function testfnc is called from the main file within a for loop, is it more efficient to create a kind of constructor in funcs.c that is called outside the loop and allocate all of the memory (assuming a fixed size) prior to calling testfnc? Rather than allocating and deallocating the memory each time testfnc is called?

I hope that makes sense, it was kind of difficult to explain.

Thanks in advance,
Chris
Back to top
View user's profile Send private message
einonm



Joined: Fri Apr 20, 2012 11:19 am
Posts: 29
Location: Cardiff, UK

PostPosted: Fri Feb 08, 2013 12:14 pm    Post subject: Reply with quote

Crispy wrote:
Thank you for your replies and my apologies for such a delayed response. Thank you as well for the tips Smile.

I have a couple of new questions if that's ok? If I used malloc to allocate some memory, is that memory contiguous? I think that's the right phrasing - i.e. each element of the array is next to each other? If so does that still hold for 2D arrays? If it isn't, would it be more efficient to make it contiguous?


It's virtually contiguous, in that the addresses are a contiguous range. It's not guaranteed to be physically contiguous though - heck, the memory may not even exist yet due to the kernel using something called 'over committing'. There are special ways of asking for physically contiguous memory (e.g. for fast graphics operations). I think at this level, you don't need to worry about it.

Crispy wrote:

My next question is a bit difficult to explain - lets assume I have 3 files. A main file, main.c, a header file which contains nothing but data, data.h - for example:
Code:
int p;
int *ptr;

and a file funcs.c which contains a function testfnc (also have funcs.h - only has function prototype). The main file includes data.h and funcs.h, however funcs.c only includes funcs.h. The function testfnc is then called from the main file. Is it more efficient to pass the integer p from data.h to the function testfnc as an argument or include the data.h file in funcs.c? I.e. from the main file: testfnc( p ); or testfnc();?

Finally, if the function testfnc has to allocate memory (using malloc or calloc), say a large array, and the function testfnc is called from the main file within a for loop, is it more efficient to create a kind of constructor in funcs.c that is called outside the loop and allocate all of the memory (assuming a fixed size) prior to calling testfnc? Rather than allocating and deallocating the memory each time testfnc is called?

I hope that makes sense, it was kind of difficult to explain.

Thanks in advance,
Chris


This code probably won't work. You can only _declare_ variables in header files, you must _define_ a variable in a .c file to use it (and then use the 'extern' keyword in the header to share it). This is because a variable declaration doesn't allocate any memory for the variable, only the variable definition does that. After the compiler gets it's hands on the code, it doesn't matter where the declarations are - you're still accessing the same memory, regardless of which c file it is in. Obviously passing that variable as a parameter involves another copy, so is less efficient (but more secure and less bug-prone), than a 'global' variable.

Again, for individual variables on a modern computer at this level, you really shouldn't care about these issues. Just write the code to do something useful!

Cheers,

Mark
_________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." --Brian Kernighan
Back to top
View user's profile Send private message
einonm



Joined: Fri Apr 20, 2012 11:19 am
Posts: 29
Location: Cardiff, UK

PostPosted: Fri Feb 08, 2013 12:22 pm    Post subject: Reply with quote

Crispy wrote:

Finally, if the function testfnc has to allocate memory (using malloc or calloc), say a large array, and the function testfnc is called from the main file within a for loop, is it more efficient to create a kind of constructor in funcs.c that is called outside the loop and allocate all of the memory (assuming a fixed size) prior to calling testfnc? Rather than allocating and deallocating the memory each time testfnc is called?
Chris


Er, yes. Allocate once and not many times is better, probably...
_________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." --Brian Kernighan
Back to top
View user's profile Send private message
Crispy



Joined: Mon May 31, 2010 7:35 pm
Posts: 57

PostPosted: Fri Feb 08, 2013 12:43 pm    Post subject: Reply with quote

Thank you for your reply einonm.
Quote:
It's virtually contiguous, in that the addresses are a contiguous range. It's not guaranteed to be physically contiguous though - heck, the memory may not even exist yet due to the kernel using something called 'over committing'. There are special ways of asking for physically contiguous memory (e.g. for fast graphics operations). I think at this level, you don't need to worry about it.

Yeah don't think I need to worry about over committing or anything like that, maybe in the future Very Happy.
Quote:
This code probably won't work. You can only _declare_ variables in header files, you must _define_ a variable in a .c file to use it (and then use the 'extern' keyword in the header to share it). This is because a variable declaration doesn't allocate any memory for the variable, only the variable definition does that.

Yeah, sorry I don't think I explained it very well. Basically in the header file I declare all the data I require for the program. That data is then initialised in the main file so assume that p was set to be 10 for example before testfnc was called.
Quote:
Er, yes. Allocate once and not many times is better, probably...

Yeah I thought it would be, the thing is I've got a loop:
Code:
for (i = 0; i < 100; i++)
    testfnc( p );

where testfnc then allocates a 1D array of size 40,000, then deallocates before leaving:
Code:
void testfnc( int j )
{
    double *test;

    test = (double *) malloc( 40000 * sizeof(*test) );

    free(test);
}

The size of the array testfnc allocates doesn't change in the 100 iterations so I thought it might be more efficient. Perhaps I'll do a test.

Thanks again,
Chris
Back to top
View user's profile Send private message
View previous topic :: View next topic  
Display posts from previous:   
Post new topic   Reply to topic    Linux Format forums Forum Index -> Programming All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Linux Format forums topic RSS feed 


Powered by phpBB © 2001, 2005 phpBB Group


Copyright 2011 Future Publishing, all rights reserved.


Web hosting by UKFast