Static array defined in one module, but used in another module

P

pozzugno

I have a module in which I define many const arrays of int of different
lengths (someone knows SNMP OIDs?).
In the same module I really use these arrays and the length is calculated by
a simple preprocessor macro (OID_LENGTH).

--- oid.c --
#define OID_LENGTH(oid) (sizeof(oid) / sizeof(oid[0]))

const int oidParam1[] = { 1, 1, 3 };
const int oidParam2[] = { 1, 2 };
const int oidParam1[] = { 2, 1 };
const int oidParam1[] = { 2, 2, 5, 4 };

int print_oid(int *oid, size_t size) {
while(size--) {
printf("%d", *oid++);
if (size) putchar('.');
}
return putchar('\n');
}

....
print_oid(oidParam1, OID_LENGTH(oidParam1));
....
---

Now the application has grown and I want to create a different module that
uses the same arrays defined in oid.c. Certainly I can write the definition
in a "oid.h" include as extern, but I can't specify the length.

--- mib.h ---
extern int oidParam1[];
extern int oidParam2[];
int print_oid(int *oid, size_t size);
---

For example, how can I print oidParam1 with print_oid() calling it from a
different module? I couldn't use OID_LENGTH macro (even if I move its
declaration to mib.h).

Any suggestions?
 
B

BartC

I have a module in which I define many const arrays of int of different
lengths (someone knows SNMP OIDs?).
In the same module I really use these arrays and the length is calculated
by
a simple preprocessor macro (OID_LENGTH).

--- oid.c --
#define OID_LENGTH(oid) (sizeof(oid) / sizeof(oid[0]))

const int oidParam1[] = { 1, 1, 3 };
const int oidParam2[] = { 1, 2 };
const int oidParam1[] = { 2, 1 };
const int oidParam1[] = { 2, 2, 5, 4 };
Now the application has grown and I want to create a different module that
uses the same arrays defined in oid.c. Certainly I can write the
definition
in a "oid.h" include as extern, but I can't specify the length.

How about defining a variable like this in same module as the arrays:

int oidParam1length = OID_LENGTH(oidParam1);

Then declaring this as extern in the other module and using this variable to
obtain the length. (Maybe you ought to stick a const prefix on it as well.).
 
B

Ben Bacarisse

I have a module in which I define many const arrays of int of different
lengths (someone knows SNMP OIDs?).
In the same module I really use these arrays and the length is calculated by
a simple preprocessor macro (OID_LENGTH).

--- oid.c --
#define OID_LENGTH(oid) (sizeof(oid) / sizeof(oid[0]))

const int oidParam1[] = { 1, 1, 3 };
const int oidParam2[] = { 1, 2 };
const int oidParam1[] = { 2, 1 };
const int oidParam1[] = { 2, 2, 5, 4 };

[duplicate names are just a typo, presumably?]
int print_oid(int *oid, size_t size) {
while(size--) {
printf("%d", *oid++);
if (size) putchar('.');
}
return putchar('\n');
}

...
print_oid(oidParam1, OID_LENGTH(oidParam1));
...
---

Now the application has grown and I want to create a different module that
uses the same arrays defined in oid.c. Certainly I can write the definition
in a "oid.h" include as extern, but I can't specify the length.

--- mib.h ---
extern int oidParam1[];
extern int oidParam2[];
int print_oid(int *oid, size_t size);
---

For example, how can I print oidParam1 with print_oid() calling it from a
different module? I couldn't use OID_LENGTH macro (even if I move its
declaration to mib.h).

Any suggestions?

A couple of things come to mind. First, can you switch from a
size-based interface to one that uses a sentinel? If there is junk int
that can never appear in an OID (-1?) putting that at the end would mean
you could avoid havint to have a length at all.

Alternatively, you could number (rather than name) the arrays and
provide access to them and their lengths via other arrays (or via access
functions).

This can be achieved without data duplication by using some
pre-processor magic. Write a file oid.h like this:

OID(oidParam1, 1, 1, 3 )
OID(oidParam2, 1, 2 )
OID(oidParam3, 2, 1 )
OID(oidParam4, 2, 2, 5, 4 )

and you can generate the tables like this:

#define OID(name, ...) static const int name[] = { __VA_ARGS__ };
#include "oid.h"

#undef OID
const int *const oid[] = {
#define OID(name, ...) name,
#include "oid.h"
};

#undef OID
const size_t oid_size[] = {
#define OID(name, ...) sizeof name/sizeof *name,
#include "oid.h"
};

Finally, you can make the index constants directly from the same source
file. This would go in a public header:

#define OID(name, ...) name,
enum {
#include "sz.h"
};

Many alternatives to this scheme are possible. You could obviously
define a struct that would contain the pointer and length as a single
object, for example.
 
J

James Kuyper

I have a module in which I define many const arrays of int of different
lengths (someone knows SNMP OIDs?).
In the same module I really use these arrays and the length is calculated by
a simple preprocessor macro (OID_LENGTH).

--- oid.c --
#define OID_LENGTH(oid) (sizeof(oid) / sizeof(oid[0]))

There's nothing specific to OID about that macro, so it should be given
a more generic name, such as ARRAY_LENGTH.
const int oidParam1[] = { 1, 1, 3 };
const int oidParam2[] = { 1, 2 };
const int oidParam1[] = { 2, 1 };
const int oidParam1[] = { 2, 2, 5, 4 };

int print_oid(int *oid, size_t size) {
while(size--) {
printf("%d", *oid++);
if (size) putchar('.');
}
return putchar('\n');
}

...
print_oid(oidParam1, OID_LENGTH(oidParam1));
...
---

Now the application has grown and I want to create a different module that
uses the same arrays defined in oid.c. Certainly I can write the definition
in a "oid.h" include as extern, but I can't specify the length.

--- mib.h ---
extern int oidParam1[];
extern int oidParam2[];

You should have included 'const' in that declaration.
int print_oid(int *oid, size_t size);
---

For example, how can I print oidParam1 with print_oid() calling it from a
different module? I couldn't use OID_LENGTH macro (even if I move its
declaration to mib.h).

mib.h:
extern const int oidParam1[];
extern const size_t oidParam1_length;

oid.c:
#include "mib.h"
const int oidParam1[] = { 1, 1, 3 };
const size_t oidParam1_length = OID_LENGTH(oidParam1);
 
P

pozz

I have a module in which I define many const arrays of int of different
lengths (someone knows SNMP OIDs?).
In the same module I really use these arrays and the length is calculated
by a simple preprocessor macro (OID_LENGTH).

--- oid.c --
#define OID_LENGTH(oid) (sizeof(oid) / sizeof(oid[0]))

const int oidParam1[] = { 1, 1, 3 };
const int oidParam2[] = { 1, 2 };
const int oidParam1[] = { 2, 1 };
const int oidParam1[] = { 2, 2, 5, 4 };

[duplicate names are just a typo, presumably?]

Oh, yes, I'm sorry.
int print_oid(int *oid, size_t size) {
while(size--) {
printf("%d", *oid++);
if (size) putchar('.');
}
return putchar('\n');
}

...
print_oid(oidParam1, OID_LENGTH(oidParam1));
...
---

Now the application has grown and I want to create a different module that
uses the same arrays defined in oid.c. Certainly I can write the definition
in a "oid.h" include as extern, but I can't specify the length.

--- mib.h ---
extern int oidParam1[];
extern int oidParam2[];
int print_oid(int *oid, size_t size);
---

For example, how can I print oidParam1 with print_oid() calling it from a
different module? I couldn't use OID_LENGTH macro (even if I move its
declaration to mib.h).

Any suggestions?

A couple of things come to mind. First, can you switch from a
size-based interface to one that uses a sentinel? If there is junk int
that can never appear in an OID (-1?) putting that at the end would mean
you could avoid havint to have a length at all.

Like a null-terminating string? This could be a good idea, but I have two
problems with this approach.

On some small machines, I don't use int, but unsigned char to have a small
memory requirements and a good range (0-255). If I'd use *signed* char, I
could use a too small range (0-127), just to have the negative sentinel.
Maybe I can use 255 as a sentinel, so leaving 0-254 values available.

Anyway I have already written many functions (an entire library) that accept
two parameters: the pointer to the array and its length. If I use the sentinel,
I should change them (or write some wrappers).

Alternatively, you could number (rather than name) the arrays and
provide access to them and their lengths via other arrays (or via access
functions).

This can be achieved without data duplication by using some
pre-processor magic. Write a file oid.h like this:

OID(oidParam1, 1, 1, 3 )
OID(oidParam2, 1, 2 )
OID(oidParam3, 2, 1 )
OID(oidParam4, 2, 2, 5, 4 )

and you can generate the tables like this:

#define OID(name, ...) static const int name[] = { __VA_ARGS__ };
#include "oid.h"

#undef OID
const int *const oid[] = {
#define OID(name, ...) name,
#include "oid.h"
};

#undef OID
const size_t oid_size[] = {
#define OID(name, ...) sizeof name/sizeof *name,
#include "oid.h"
};

Finally, you can make the index constants directly from the same source
file. This would go in a public header:

#define OID(name, ...) name,
enum {
#include "sz.h"
};

Many alternatives to this scheme are possible. You could obviously
define a struct that would contain the pointer and length as a single
object, for example.

Yes, this is good. I like it. I already have used a similar approach for
other purposes.

Thank you for your answer.
 
C

Charles Richmond

I have a module in which I define many const arrays of int of different
lengths (someone knows SNMP OIDs?).
In the same module I really use these arrays and the length is calculated
by
a simple preprocessor macro (OID_LENGTH).

--- oid.c --
#define OID_LENGTH(oid) (sizeof(oid) / sizeof(oid[0]))

const int oidParam1[] = { 1, 1, 3 };
const int oidParam2[] = { 1, 2 };
const int oidParam1[] = { 2, 1 };
const int oidParam1[] = { 2, 2, 5, 4 };

int print_oid(int *oid, size_t size) {
while(size--) {
printf("%d", *oid++);
if (size) putchar('.');
}
return putchar('\n');
}

...
print_oid(oidParam1, OID_LENGTH(oidParam1));
...
---

Now the application has grown and I want to create a different module that
uses the same arrays defined in oid.c. Certainly I can write the
definition
in a "oid.h" include as extern, but I can't specify the length.

--- mib.h ---
extern int oidParam1[];
extern int oidParam2[];
int print_oid(int *oid, size_t size);
---

For example, how can I print oidParam1 with print_oid() calling it from a
different module? I couldn't use OID_LENGTH macro (even if I move its
declaration to mib.h).

Any suggestions?

Suggestion: Create an "oid.h" file that contains the definitions for the
*static* arrays. Then include the file in *both* modules. You end up with
*two* copies of the constant arrays... but you only have to change the
arrays in *one* place (the "oid.h" file) if there is need for them to
change.
 
E

Eric Sosman

I have a module in which I define many const arrays of int of different
lengths (someone knows SNMP OIDs?).
In the same module I really use these arrays and the length is calculated by
a simple preprocessor macro (OID_LENGTH).

--- oid.c --
#define OID_LENGTH(oid) (sizeof(oid) / sizeof(oid[0]))

const int oidParam1[] = { 1, 1, 3 };
const int oidParam2[] = { 1, 2 };
[...]
Any suggestions?

Have you considered packaging both the length and a pointer
in a single struct?

// In a header somewhere:
struct oid {
size_t size;
const int *data;
};
extern const struct oid oidParam1;
extern const struct oid oidParam2;

// In your defining module:
static const int oid1[] = { 1, 1, 3 };
const struct oid oidParam1 = { OID_LENGTH(oid1), oid1 };
static const int oid2[] = { 1, 2 };
const struct oid oidParam2 = { OID_LENGTH(oid2), oid2 };

This could be lipsticked a bit with additional macro magic,
if desired.
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top