473,394 Members | 2,090 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

sizeof extern arrays

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
7 9001
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
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
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 (40°39.22'N, 111°50.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
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
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
"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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: nzanella | last post by:
Hello, I just thought I would share the following observation with the rest of the group. The sizeof operator seems to act differently according to whether the number of elements in the array is...
6
by: Howard Kaikow | last post by:
Given: private struct PROCESSENTRY32 { public int dwSize; public int cntUsage; public int th32ProcessID; public int th32DefaultHeapID; public int th32ModuleID;
15
by: stand__sure | last post by:
Having recently had a need to use ZeroMemory from the kernel32.dll, I "discovered" that there is apparently no .NET equivalent to the c/c++ sizeof operator -- one does exist in the Marshall...
7
by: ruffiano | last post by:
I have a file called first.cpp that contains the following declarations: static const char *MY_STRING1 = "My first string"; static const char *MY_STRING2 = "My second string" If I wanted to use...
18
by: sss555 | last post by:
Hi, I tried to share some data between 2 .cc files hence declared the arrays of structure as extern in one of the .cc files. However I get abnormal entries in the original array entries...
17
by: kevin | last post by:
this is my programm .... char *p="abcde"; char a="abcde"; ..... printf("the size of p is:%d\n",sizeof(p)); printf("the size of a is:%d\n",sizeof(a)); ........
6
by: sinbad | last post by:
hi, check out the following program ... a.c ----- extern void fun(); int a; int main () {
3
by: CptDondo | last post by:
I've got a question on the proper handling of sizeof. I have two files; a.c and b.c In b.c I have: struct Key en_keys = { {EN_ENTER, DELAY, NULL}, };
27
by: CodeMonk3y | last post by:
gotta question on sizeof keyword does the sizeof keyword calcuates the size at compile time or run time ?? -- Posted on news://freenews.netfront.net - Complaints to news@netfront.net --
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.