473,785 Members | 2,354 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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 9041
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*********@su n.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.118 7$Oc1.206@newsf e4-gui>
Kieran Simkin <ki****@digit al-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_DEFI NE char muser[256];

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

#ifndef DECLARE_OR_DEFI NE
#define DECLARE_OR_DEFI NE extern /* default is "declare" */
#endif

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

#define DECLARE_OR_DEFI NE /* 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****@digit al-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_declaratio ns.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*********@su n.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****@digit al-crocus.com> wrote in message
news:T28wc.1205 $Oc1.855@newsfe 4-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*********@su n.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
4636
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 known. Hence when passing arrays to functions the number of elements in the array must always be passed as an argument. If STL is available then people can just use vectors of course. Anyways, I guess this stuff is pretty standard. Well, have a...
6
6698
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
4520
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 namespace, but it fails when passed a managed type. I poked around the Reflection namespace, but found nothing that fits the bill. Is there a runtime equivalent to sizeof in ..NET?
7
454
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 MY_STRING1 and MY_STRING2 in a header file, would the following be correct? extern static const char *MY_STRING1; extern static const char *MY_STRING2;
18
9318
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 otherwise I wouldn't have got. file1.h --------- struct Mylistdetails { int id;
17
1923
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
2984
by: sinbad | last post by:
hi, check out the following program ... a.c ----- extern void fun(); int a; int main () {
3
2384
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
5609
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
10350
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10157
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10097
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9957
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8983
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6742
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5386
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5518
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3658
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.