By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,364 Members | 1,518 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,364 IT Pros & Developers. It's quick & easy.

sizeof extern arrays

P: n/a
I have in my project in main.c a number of arrays defined like this (outside
of any functions):
char muser[256], mpass[256];
I'm declaring them in a number of other .c files (inside functions) like
this:
extern char muser[], mpass[];

However, in one of these functions outside of main.c I need to snprintf into
these buffers. Usually when using snprintf I call it like this:
snprintf(muser, sizeof muser, "text");
My problem is that sizeof does not work on extern arrays declared as above -
GCC returns the following error:
config.c:41: sizeof applied to an incomplete type

What's the best solution to this problem? I'm assuming it's valid to specify
an array's size when declaring it with extern, but I'd rather not have magic
numbers scattered all over my source files. Is there any way I can use
sizeof or similar on externally defined arrays without specifying array
dimensions in each source file?

Thanks.

~Kieran Simkin
Digital Crocus
http://digital-crocus.com/
Nov 14 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
Kieran Simkin wrote:
I have in my project in main.c a number of arrays defined like this (outside
of any functions):
char muser[256], mpass[256];
I'm declaring them in a number of other .c files (inside functions) like
this:
extern char muser[], mpass[];

However, in one of these functions outside of main.c I need to snprintf into
these buffers. Usually when using snprintf I call it like this:
snprintf(muser, sizeof muser, "text");
My problem is that sizeof does not work on extern arrays declared as above -
GCC returns the following error:
config.c:41: sizeof applied to an incomplete type

What's the best solution to this problem? I'm assuming it's valid to specify
an array's size when declaring it with extern, but I'd rather not have magic
numbers scattered all over my source files. Is there any way I can use
sizeof or similar on externally defined arrays without specifying array
dimensions in each source file?


The best solution is the same as for any other identifier
with external linkage: Write the declaration once in a header
file, and #include that header file in each source module that
needs access to the identifiers. It may not seem obvious, but
the source file that actually *defines* the identifier should
also #include the header.

/* simkin.h */
extern char muser[256];
extern char mpass[256];

/* simkin.c */
#include "simkin.h"
char muser[256];
char mpass[256];

/* simkin2.c */
#include <stdio.h>
#include "simkin.h"
void print_them(void) {
printf ("muser = %s\n", muser);
printf ("mpass = %s\n", mpass);
}

One other observation: data identifiers with external
linkage ("global variables") should be used sparingly. Sad
experience has demonstrated that programs with many global
variables are much harder to maintain, extend, and debug
than programs with few of them. From the names you have
given your variables, I strongly suspect that these data
objects are *not* good candidates for globalization.

Proceed At Your Own Risk.

--
Er*********@sun.com

Nov 14 '05 #2

P: n/a
Ah perfect, that's exactly the kind of solution I was looking for.
I've read in the c.l.c FAQ that using externally linked variables a lot
isn't a good idea. Currently what I'm doing is defining a few buffers which
hold various config options (like the mysql username and password the
program should be using etc). These config options are read in from a file
and then declared with extern individually in each of the source files that
require them. Adding a new config option is quite easy because I just have
to make a modification to my config file reading function, define a buffer
to store it in and declare the buffer I wish to use in the new source file
I'm writing.
I've been thinking about replacing this with a linked list containing all
the config options in a struct like this:

struct confignode {
char name[256];
char value[256];
struct confignode *next;
};

However, then every time I wanted to use a config option I would have to
call a function to traverse the list which in real terms probably wouldn't
mean a significant performance hit, but it seems wasteful. Any suggestions
on a better way to hold config options without using externally linked
variables?
~Kieran Simkin
Digital Crocus
http://digital-crocus.com/

"Eric Sosman" <Er*********@sun.com> wrote in message
news:40**************@sun.com...
Kieran Simkin wrote:
I have in my project in main.c a number of arrays defined like this (outside of any functions):
char muser[256], mpass[256];
I'm declaring them in a number of other .c files (inside functions) like
this:
extern char muser[], mpass[];

However, in one of these functions outside of main.c I need to snprintf into these buffers. Usually when using snprintf I call it like this:
snprintf(muser, sizeof muser, "text");
My problem is that sizeof does not work on extern arrays declared as above - GCC returns the following error:
config.c:41: sizeof applied to an incomplete type

What's the best solution to this problem? I'm assuming it's valid to specify an array's size when declaring it with extern, but I'd rather not have magic numbers scattered all over my source files. Is there any way I can use
sizeof or similar on externally defined arrays without specifying array
dimensions in each source file?


The best solution is the same as for any other identifier
with external linkage: Write the declaration once in a header
file, and #include that header file in each source module that
needs access to the identifiers. It may not seem obvious, but
the source file that actually *defines* the identifier should
also #include the header.

/* simkin.h */
extern char muser[256];
extern char mpass[256];

/* simkin.c */
#include "simkin.h"
char muser[256];
char mpass[256];

/* simkin2.c */
#include <stdio.h>
#include "simkin.h"
void print_them(void) {
printf ("muser = %s\n", muser);
printf ("mpass = %s\n", mpass);
}

One other observation: data identifiers with external
linkage ("global variables") should be used sparingly. Sad
experience has demonstrated that programs with many global
variables are much harder to maintain, extend, and debug
than programs with few of them. From the names you have
given your variables, I strongly suspect that these data
objects are *not* good candidates for globalization.

Proceed At Your Own Risk.

--
Er*********@sun.com

Nov 14 '05 #3

P: n/a
In article <news:kn7wc.1187$Oc1.206@newsfe4-gui>
Kieran Simkin <ki****@digital-crocus.com> writes (in part):
[in one file]
char muser[256], mpass[256]; [and in others]extern char muser[], mpass[];

However, in one of these functions outside of main.c I need to snprintf into
these buffers. Usually when using snprintf I call it like this:
snprintf(muser, sizeof muser, "text");
My problem is that sizeof does not work on extern arrays declared as above -
GCC returns the following error:
config.c:41: sizeof applied to an incomplete type

What's the best solution to this problem?


What's the "best" way to get across a lake -- boat, bridge, or going
around the outside?

There are lots of options, none clearly "best".

Here is one option:

main.c:
char muser[256];
size_t muser_size = sizeof muser;
...

other.c:
extern char muser[];
extern size_t muser_size;
...
val = snprintf(muser, muser_size, "text");

Here is another:

main.c:
#include "user.h"
char muser[MUSER_SIZE];
...

other.c:
#include "user.h"
...
val = snprintf(muser, MUSER_SIZE, "text"); /* or sizeof */

user.h:
#define MUSER_SIZE 256
extern char muser[MUSER_SIZE];

Yet another is to have a user.h as above, but use something like:

DECLARE_OR_DEFINE char muser[256];

and make sure that precisely one .c file defines "DECLARE_OR_DEFINE"
as the empty string, while the rest define it as "extern". For
instance, put:

#ifndef DECLARE_OR_DEFINE
#define DECLARE_OR_DEFINE extern /* default is "declare" */
#endif

near the top of user.h, and then have main.c do:

#define DECLARE_OR_DEFINE /* nothing, i.e., define */
#include "user.h"

This last solution uses the least redundancy, but I personally prefer
the others.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #4

P: n/a
In 'comp.lang.c', "Kieran Simkin" <ki****@digital-crocus.com> wrote:
I have in my project in main.c a number of arrays defined like this
(outside of any functions):
char muser[256], mpass[256];
I'm declaring them in a number of other .c files (inside functions) like
this:
extern char muser[], mpass[];


Do it the reverse way :

The definitions (.c):

#include "the_declarations.h"
char muser[], mpass[];

The declarations (.h) :

extern char muser[256], mpass[256];

Simple, safe and portable.

--
-ed- get my email here: http://marreduspam.com/ad672570
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=c99
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/
Nov 14 '05 #5

P: n/a
In 'comp.lang.c', Eric Sosman <Er*********@sun.com> wrote:
/* simkin.h */
extern char muser[256];
extern char mpass[256];

/* simkin.c */
#include "simkin.h"
char muser[256];
char mpass[256];


Considering that the size is gven in the declaration, isn't is possible to
get rid of the size here ?

char muser[];
char mpass[];

it simplifies the maintenance.

--
-ed- get my email here: http://marreduspam.com/ad672570
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=c99
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/
Nov 14 '05 #6

P: n/a
"Kieran Simkin" <ki****@digital-crocus.com> wrote in message
news:T28wc.1205$Oc1.855@newsfe4-gui...
Ah perfect, that's exactly the kind of solution I was looking for.
I've read in the c.l.c FAQ that using externally linked variables a lot
isn't a good idea. Currently what I'm doing is defining a few buffers which hold various config options (like the mysql username and password the
program should be using etc). These config options are read in from a file
and then declared with extern individually in each of the source files that require them. Adding a new config option is quite easy because I just have
to make a modification to my config file reading function, define a buffer
to store it in and declare the buffer I wish to use in the new source file
I'm writing.
I've been thinking about replacing this with a linked list containing all
the config options in a struct like this:

struct confignode {
char name[256];
char value[256];
struct confignode *next;
};

However, then every time I wanted to use a config option I would have to
call a function to traverse the list which in real terms probably wouldn't
mean a significant performance hit, but it seems wasteful. Any suggestions
on a better way to hold config options without using externally linked
variables?


You could malloc() the memory for the data, and pass
around a pointer to it as function argument(s).

If you'll be using a linked list, you'll be malloc'ing
anyway.

-Mike
Nov 14 '05 #7

P: n/a
In <40**************@sun.com> Eric Sosman <Er*********@sun.com> writes:
Kieran Simkin wrote:
I have in my project in main.c a number of arrays defined like this (outside
of any functions):
char muser[256], mpass[256];
I'm declaring them in a number of other .c files (inside functions) like
this:
extern char muser[], mpass[];

However, in one of these functions outside of main.c I need to snprintf into
these buffers. Usually when using snprintf I call it like this:
snprintf(muser, sizeof muser, "text");
My problem is that sizeof does not work on extern arrays declared as above -
GCC returns the following error:
config.c:41: sizeof applied to an incomplete type

What's the best solution to this problem? I'm assuming it's valid to specify
an array's size when declaring it with extern, but I'd rather not have magic
numbers scattered all over my source files. Is there any way I can use
sizeof or similar on externally defined arrays without specifying array
dimensions in each source file?


The best solution is the same as for any other identifier
with external linkage: Write the declaration once in a header
file, and #include that header file in each source module that
needs access to the identifiers. It may not seem obvious, but
the source file that actually *defines* the identifier should
also #include the header.

/* simkin.h */
extern char muser[256];
extern char mpass[256];

/* simkin.c */
#include "simkin.h"
char muser[256];
char mpass[256];

/* simkin2.c */
#include <stdio.h>
#include "simkin.h"
void print_them(void) {
printf ("muser = %s\n", muser);
printf ("mpass = %s\n", mpass);
}


OTOH, if the magic value 256 changes, you want to minimise the number of
places that need editing. So, it's better to define one or two macros
(two if the sizes of the two arrays are unrelated) in simkin.h and use
them in both simkin.h and simkin.c. This approach also completely removes
any need for the sizeof operator, BTW.

/* simkin.h */
#define MUSER_SIZE 256
#define MPASS_SIZE 256

extern char muser[MUSER_SIZE];
extern char mpass[MPASS_SIZE];

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.