Splitting up code ?

S

Skybuck Flying

Hi,

I would like to split main.c which contains all code into the following

Step 1. Machine.h
Step 2. drand.h and drand.c
Step 3. nrand.h and nrand.c

Main.c then only contains some test code.

The trouble starts at Step 2.

1. Machine.h should only contain integer types.

I have cut away any redundant/unneeded comments to safe space.

*** begin of Machine.h ***

#ifndef __MACHINE_H__
#define __MACHINE_H__

typedef signed __int8 sint8;
typedef unsigned __int8 uint8;
typedef signed __int16 sint16;
typedef unsigned __int16 uint16;
typedef signed __int32 sint32;
typedef unsigned __int32 uint32;
typedef signed __int64 sint64;
typedef unsigned __int64 uint64;

#endif

*** end of Machine.h ***

So far this worked.

2. Splitting up code into drand.c and drand.h

This is were the trouble starts ;)

*** begin of drand.h ***

#ifndef __DRAND_H__
#define __DRAND_H__

#include "Machine.h"

struct drand48_data
{
uint16 __x[3];
uint16 __old_x[3];
uint16 __c;
uint16 __init;
uint64 __a;
};

/* Global state for non-reentrant functions. */
struct drand48_data __libc_drand48_data;

sint32 __drand48_iterate( uint16 xsubi[3], struct drand48_data *buffer );

#endif

*** end of drand.h ***

*** begin of drand.c ***

#include "machine.h"
#include "drand.h"

sint32 __drand48_iterate( uint16 xsubi[3], struct drand48_data *buffer )
{
uint64 X;
uint64 result;

if (buffer->__init == 0)
{
buffer->__a = 0x5deece66du;
buffer->__c = 0xb;
buffer->__init = 1;
}

X = (uint64) xsubi[2] << 32 | (uint32) xsubi[1] << 16 | xsubi[0];

result = X * buffer->__a + buffer->__c;

xsubi[0] = (uint16) ( result & 0xffff );
xsubi[1] = (uint16) ( (result >> 16) & 0xffff );
xsubi[2] = (uint16) ( (result >> 32) & 0xffff );

return 0;
}

*** end of drand.c ***

*** begin of main.c ***

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

#include "machine.h"
#include "drand.h"

// nrand interface

// forward declaration so that it can later be split up into .h and .c
sint32 nrand48 (uint16 xsubi[3]);

// nrand implementation

sint32 __nrand48_r ( uint16 xsubi[3], struct drand48_data *buffer, sint32
*result )
{

if (__drand48_iterate (xsubi, buffer) < 0)
{
return -1;
}

if (sizeof (unsigned short int) == 2)
{
*result = xsubi[2] << 15 | xsubi[1] >> 1;
}
else
{
*result = xsubi[2] >> 1;
}

return 0;
}

sint32 nrand48 (uint16 xsubi[3])
{
sint32 result;

(void) __nrand48_r (xsubi, &__libc_drand48_data, &result);

return result;
}

// test program

int main()
{
uint16 state48[3];

printf("%d \n", nrand48(state48) );
printf("%d \n", nrand48(state48) );
printf("%d \n", nrand48(state48) );
printf("%d \n", nrand48(state48) );
printf("%d \n", nrand48(state48) );

// the output is:

// 1288336289
// 893806678
// 810173679
// 37620279
// 474250687

return 0;
}

*** end of main.c ***

I am also using the #ifndef and #define and #endif stuff for headers as
learned in college... is that wise to do ?

Since I have seen other code *without* #ifndef #define #endif in the
headers. ?

( The ldpc source code does not use it in the headers )

I think the visual c settings are correct:

1. Machine.h, drand.h are included in header section.
2. drand.c and main.c are included in source files section.

For some reason the test program main.c won't compile:

--------------------Configuration: TestNRand48 - Win32
Debug--------------------
Compiling...
Main.cpp
Linking...
Main.obj : error LNK2001: unresolved external symbol "__int32 __cdecl
__drand48_iterate(unsigned __int16 * const,struct drand48_data *)"
(?__drand48_iterate@@YA_HQA_GPAUdrand48_data@@@Z)
Debug/TestNRand48.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

TestNRand48.exe - 2 error(s), 0 warning(s)

Why is that ?

Bye,
Skybuck.
 
C

Christopher Benson-Manica

For some reason the test program main.c won't compile:

main.c compiles just fine. Your error is occurring at the linking
stage.
I think the visual c settings are correct:

Apparently not, since the linker is not happy.
Main.obj : error LNK2001: unresolved external symbol "__int32 __cdecl
__drand48_iterate(unsigned __int16 * const,struct drand48_data *)"
(?__drand48_iterate@@YA_HQA_GPAUdrand48_data@@@Z)
Debug/TestNRand48.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
Why is that ?

This isn't the best place to ask:

http://www.ungerhu.com/jxh/clc.welcome.txt
http://www.eskimo.com/~scs/C-faq/top.html
http://benpfaff.org/writings/clc/off-topic.html

Try a newsgroup related to your platform.
 
D

Darrell Grainger

Hi,

I would like to split main.c which contains all code into the following

Step 1. Machine.h
Step 2. drand.h and drand.c
Step 3. nrand.h and nrand.c

Main.c then only contains some test code.

The trouble starts at Step 2.

1. Machine.h should only contain integer types.

I have cut away any redundant/unneeded comments to safe space.

[bunch of code snipped]
I am also using the #ifndef and #define and #endif stuff for headers as
learned in college... is that wise to do ?

Only if you understand the implications for your environment. I like to
avoid using header guards. For example, if I #include "drand.h" twice, I
compile the first source file and it defines storage for the global
variables. I then compile the second source file and it defines storage for
the global variables. The moment I attempt to link the two object files I
get a conflict because they both thought they needed to define the global
variable.

The opposite situation is that header guards can sometimes cause a source
file to not be aware of a function or global variable in a different file.
For example, the compiler compiles the first source file that includes a
header file with guards. The #define from the header file carries over to
the next source file getting compiled and the second source file is blind
to the header file.
Since I have seen other code *without* #ifndef #define #endif in the
headers. ?

Here is how I would do it:

- Start with a single source file that compiles and links okay.
- Copy all the functions and global varaibles that I believe goes with
drand.c into drand.c.
- Create a drand.h that has prototypes and extern declarations for all the
functions and global variables.
- #include "drand.h" in drand.c. This will generate a compile time error
if you ever change the information in drand.c but not in drand.h
- create a main.c (but call it something more descriptive) that #includes
"drand.h" and has just test code for the functions in drand.c

If you want you can also move some of the typedef and macro lines into
machine.h. The most important rule is never create a definition in a
header. This means headers never allocate storage and can therefore be
#included multiple times. This eliminates the need for header guards.
( The ldpc source code does not use it in the headers )

I think the visual c settings are correct:

1. Machine.h, drand.h are included in header section.
2. drand.c and main.c are included in source files section.

For some reason the test program main.c won't compile:

--------------------Configuration: TestNRand48 - Win32
Debug--------------------
Compiling...
Main.cpp
Linking...
Main.obj : error LNK2001: unresolved external symbol "__int32 __cdecl
__drand48_iterate(unsigned __int16 * const,struct drand48_data *)"
(?__drand48_iterate@@YA_HQA_GPAUdrand48_data@@@Z)
Debug/TestNRand48.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

TestNRand48.exe - 2 error(s), 0 warning(s)

Why is that ?

This just looks like you compiled only main.cpp and forgot to add drand.c
to your project.
 
S

Skybuck Flying

Darrell Grainger said:
Hi,

I would like to split main.c which contains all code into the following

Step 1. Machine.h
Step 2. drand.h and drand.c
Step 3. nrand.h and nrand.c

Main.c then only contains some test code.

The trouble starts at Step 2.

1. Machine.h should only contain integer types.

I have cut away any redundant/unneeded comments to safe space.

[bunch of code snipped]
I am also using the #ifndef and #define and #endif stuff for headers as
learned in college... is that wise to do ?

Only if you understand the implications for your environment. I like to
avoid using header guards. For example, if I #include "drand.h" twice, I
compile the first source file and it defines storage for the global
variables. I then compile the second source file and it defines storage for
the global variables. The moment I attempt to link the two object files I
get a conflict because they both thought they needed to define the global
variable.

The opposite situation is that header guards can sometimes cause a source
file to not be aware of a function or global variable in a different file.
For example, the compiler compiles the first source file that includes a
header file with guards. The #define from the header file carries over to
the next source file getting compiled and the second source file is blind
to the header file.
Since I have seen other code *without* #ifndef #define #endif in the
headers. ?

Here is how I would do it:

- Start with a single source file that compiles and links okay.
- Copy all the functions and global varaibles that I believe goes with
drand.c into drand.c.
- Create a drand.h that has prototypes and extern declarations for all the
functions and global variables.
- #include "drand.h" in drand.c. This will generate a compile time error
if you ever change the information in drand.c but not in drand.h
- create a main.c (but call it something more descriptive) that #includes
"drand.h" and has just test code for the functions in drand.c

Thanks I will try this out later and tell you how it goes ;) :D... see my
other question below ;)
If you want you can also move some of the typedef and macro lines into
machine.h. The most important rule is never create a definition in a
header. This means headers never allocate storage and can therefore be
#included multiple times. This eliminates the need for header guards.

Ok, so quick question:

Won't that lead to including forward declarations many times ?

So in other words my question would be:

Is it ok to have the same forward declaration multiple times ?

I think not ?

for example:

int nrand48( short int blabla[3] );

int nrand48( short int blabla[3] );

int nrand48( short int blabla[3] );

int nrand48( short int blabla[3] );

Those are 4 forward declarations...

Is that allowed in C ???
 
S

Skybuck Flying

Apperently this is allowed WOH

( Multiple forward declarations )

#include <stdio.h>

typedef signed __int8 sint8;
typedef unsigned __int8 uint8;
typedef signed __int16 sint16;
typedef unsigned __int16 uint16;
typedef signed __int32 sint32;
typedef unsigned __int32 uint32;
typedef signed __int64 sint64;
typedef unsigned __int64 uint64;


sint32 function_test();

sint32 function_test();

sint32 function_test();


sint32 function_test()
{

return 1000;

}


int main()
{
printf("program started\n");


printf("function test: %d \n", function_test() );


printf("program finished\n");

return 0;
}
 
S

Skybuck Flying

Well,

It turned out the file name was *not* main.c *but* main.cpp.

And wacky enough ^^ that caused the problem ? HUH !? :)

As soon as I renamed main.cpp to main.c it compiled just perfectly !

The dumb thing is... why does Visual C/C++ 6.0 always use the extension
..cpp... why doesn't it have a new file option for .c ?!

THAT S PRETTY F****** STUPID =D

No hard feelings towards C itself :D

Oh yeah and by the way... I tested your method (without #ifndef in headers
etc ) and I tested the 'docent/college' method (with #ifndef in headers etc)
and both just worked fine :D

Also thank you for explaining how global/unit/library/storage variables
work...

I now understand that headers can contain the extern keyword + a type + a
variable name - initializer.

For example:

// In your words this is invalid for headers because this is storage !
extern sint32 global_a = 12345;

This is the right way:

extern sint32 global_a; // no storage :) just types which is ok in C

Then later in .c files:

sint32 global_a = 12345; // storage in C file :)

Cool.

Bye,
Skybuck.
 
A

Arthur J. O'Dwyer

It turned out the file name was *not* main.c *but* main.cpp.
And wacky enough ^^ that caused the problem ? HUH !? :)
As soon as I renamed main.cpp to main.c it compiled just perfectly !

Makes sense. "cpp" *is* an extension associated with C++, not C,
and they *are* different languages, as people have, I think, been
saying for a while here. :)
The dumb thing is... why does Visual C/C++ 6.0 always use the extension
.cpp... why doesn't it have a new file option for .c ?!
THAT S PRETTY F****** STUPID =D

That's Microsoft for ya. But on their account... I thought the
name of the product was "Visual C++." That would be a pretty big
hint as to the language involved, wouldn't it? (OT: I strongly
recommend gcc for people interested in learning the language, rather
than the Microsoft GUI interface. Check out DJGPP if that sounds
like your style.)

// In your words this is invalid for headers because this is storage !
extern sint32 global_a = 12345;

Right. If you give it an initial value, it will need a place to
*put* that value. And if you #include that line twice, it will try
to make a place to put that value, *twice*. And that's bad.
This is the right way:

extern sint32 global_a; // no storage :) just types which is ok in C

Yup.
Then later in .c files:

sint32 global_a = 12345; // storage in C file :)

Yup.

Yup.


-Arthur
 
S

Skybuck Flying

Arthur J. O'Dwyer said:
Makes sense. "cpp" *is* an extension associated with C++, not C,
and they *are* different languages, as people have, I think, been
saying for a while here. :)


That's Microsoft for ya. But on their account... I thought the
name of the product was "Visual C++." That would be a pretty big
hint as to the language involved, wouldn't it? (OT: I strongly
recommend gcc for people interested in learning the language, rather
than the Microsoft GUI interface. Check out DJGPP if that sounds
like your style.)

Cr*p lol.

It does say Visual C++ 6.0.

Well previously it was called Visual C/C++ 5.0 I think ?!
 
M

Mark A. Odell

Hi,

I would like to split main.c which contains all code into the following

Step 1. Machine.h
Step 2. drand.h and drand.c
Step 3. nrand.h and nrand.c

You want to split up the code, and vishal wants to pack it all into one
file. Isn't there a happy medium? :)
 
S

Skybuck Flying

Then again you're wrong.

At least occurding to others :)

Visual C++ 6.0 also has a C compiler.

It depends on the file extension.

..C <- C compiler
..CPP <- CPP compiler.

Though my complaint about Visual C++ 6.0 not having an option/menu to create
a .C file is still a valid complaint ;) =D
 
B

Ben Pfaff

Mark A. Odell said:
You want to split up the code, and vishal wants to pack it all into one
file. Isn't there a happy medium? :)

vishal and Skybuck could just trade files.
 
R

Richard Bos

Skybuck Flying said:
It turned out the file name was *not* main.c *but* main.cpp.

And wacky enough ^^ that caused the problem ? HUH !? :)

I told you this two days ago. _Twice_. Do you even read the replies you
get?
THAT S PRETTY F****** STUPID =D

Ho-hum.

Richard
 
S

Skybuck Flying

Richard Bos said:
I told you this two days ago. _Twice_. Do you even read the replies you
get?

Sure I do... however I am not sure if it was two days ago.. I think maybe
about the same time...

If it was two days ago I must have read over it =D
 
D

Dave Thompson

The dumb thing is... why does Visual C/C++ 6.0 always use the extension
.cpp... why doesn't it have a new file option for .c ?!
<OT implementation=MSVC> It's just the default. Type foo.c .

Alternatively, create the file with Explorer and/or any other editor
and File / Add to project / Files, or rightclick / Add files to
project, or IIRC just drag&drop. </>

- David.Thompson1 at worldnet.att.net
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top