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

Discussion in 'C Programming' started by pozzugno@gmail.com, Oct 24, 2012.

  1. Guest

    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?
     
    , Oct 24, 2012
    #1
    1. Advertising

  2. BartC Guest

    <> wrote in message
    news:...
    > 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.).


    --
    Bartc
     
    BartC, Oct 24, 2012
    #2
    1. Advertising

  3. writes:

    > 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.

    --
    Ben.
     
    Ben Bacarisse, Oct 24, 2012
    #3
  4. James Kuyper Guest

    On 10/24/2012 06:45 AM, wrote:
    > 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);
    --
    James Kuyper
     
    James Kuyper, Oct 24, 2012
    #4
  5. pozz Guest

    On Wednesday, October 24, 2012 1:28:36 PM UTC+2, Ben Bacarisse wrote:
    > writes:
    >
    > > 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.
     
    pozz, Oct 24, 2012
    #5
  6. <> wrote in message
    news:...
    >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.

    --

    numerist at aquaporin4 dot com
     
    Charles Richmond, Oct 24, 2012
    #6
  7. Eric Sosman Guest

    On 10/24/2012 6:45 AM, wrote:
    > 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.

    --
    Eric Sosman
    d
     
    Eric Sosman, Oct 24, 2012
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kabeer
    Replies:
    6
    Views:
    3,245
    Thomas Matthews
    Aug 21, 2003
  2. rashmi
    Replies:
    5
    Views:
    5,113
  3. Oodini
    Replies:
    1
    Views:
    1,795
    Keith Thompson
    Sep 27, 2005
  4. Replies:
    6
    Views:
    393
  5. Travis
    Replies:
    6
    Views:
    549
    Markus Schoder
    Jun 28, 2007
Loading...

Share This Page