Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Is this a good habit?

Reply
Thread Tools

Is this a good habit?

 
 
Snis Pilbor
Guest
Posts: n/a
 
      07-27-2006
Hi,

It seems pretty common to return pointers to a static array, for
example:

char *capitalize( char *name )
{
static char buf[MAX_STRING_LENGTH];

sprintf( buf, "%s", name );
if ( *buf >= 'a' && *buf <= 'z' )
*buf += 'A' - 'a';

return buf;
}

But when I do something like this, I like to instead keep a static
pointer and malloc it the first time, to save space in whatever bank
static memory is stored in, since I have this vague idea that if too
much space is used in static memory bad things will happen? So I do
this instead:

char *capitalize( char *name )
{
static char *buf;

if ( !buf )
{
buf = malloc( MAX_STRING_LENGTH );
if ( !buf ) return name;
}

sprintf( buf, "%s", name );
if ( *buf >= 'a' && *buf <= 'z' )
*buf += 'A' - 'a';

return buf;
}

Here is how I analyze both methods as far as efficiency:

* the 2nd version uses less space in delicate "static memory" (not sure
what that's called)
* the 1st is much faster on the first call
* the 1st is slightly faster the other calls (assuming the first time,
malloc worked)
* the 1st does not assume the OS will do appropriate cleanup on exit,
as the 2nd does
* the 1st is quicker to type

I wonder which method is really best. I suppose it depends on how big
MAX_STRING_LENGTH is. I assume for instance one wouldn't want to
casually declare multi-hundred-kilobyte static arrays?

Thanks for any help =)

 
Reply With Quote
 
 
 
 
EventHelix.com
Guest
Posts: n/a
 
      07-27-2006

Snis Pilbor wrote:
> Hi,
>
> It seems pretty common to return pointers to a static array, for
> example:
>
> char *capitalize( char *name )
> {
> static char buf[MAX_STRING_LENGTH];
>
> sprintf( buf, "%s", name );
> if ( *buf >= 'a' && *buf <= 'z' )
> *buf += 'A' - 'a';
>
> return buf;
> }


IMHO, Use of static variables inside functions is not a good idea. You
will end up with code that is not thread safe. The function will
misbehave if multiple concurrently running threads are invoking the
function with static variables.

--
VisualEther Protocol Analyzer 1.0 -
http:://www.EventHelix.com/VisualEther
Visual protocol analysis and sequence diagram generation from Ethereal

 
Reply With Quote
 
 
 
 
Snis Pilbor
Guest
Posts: n/a
 
      07-27-2006

EventHelix.com wrote:
> Snis Pilbor wrote:
> > Hi,
> >
> > It seems pretty common to return pointers to a static array, for
> > example:
> >
> > char *capitalize( char *name )
> > {
> > static char buf[MAX_STRING_LENGTH];
> >
> > sprintf( buf, "%s", name );
> > if ( *buf >= 'a' && *buf <= 'z' )
> > *buf += 'A' - 'a';
> >
> > return buf;
> > }

>
> IMHO, Use of static variables inside functions is not a good idea. You
> will end up with code that is not thread safe. The function will
> misbehave if multiple concurrently running threads are invoking the
> function with static variables.
>


Yes, of course, it goes without saying in either case one must exercise
caution.
IMHO one of the most beautiful things about C is that it allows you
such flexibility. It does not assume you are a baby and hold your
hand.
If I wanted a language where various people told me "Oh you can't do
that, it's too dangerous", I would program Java =) Thanks for the word
of warning anyway, though.
I will continue to return pointers to static arrays in time sensitive
functions because I am, and those who work under me are, smart enough
to know what we're doing. =)

 
Reply With Quote
 
Morris Dovey
Guest
Posts: n/a
 
      07-27-2006
Snis Pilbor (in (E-Mail Removed) m)
said:

| I will continue to return pointers to static arrays in time
| sensitive functions because I am, and those who work under me are,
| smart enough to know what we're doing. =)

Hmm. Seems to me that for time-sensitive functions the 'smart' thing
to do would be to use strcpy() to make the copy and do the
single-character conversion from lower- to upper-case inline.

--
Morris Dovey
DeSoto Solar
DeSoto, Iowa USA
http://www.iedu.com/DeSoto


 
Reply With Quote
 
Christopher Benson-Manica
Guest
Posts: n/a
 
      07-27-2006
Snis Pilbor <(E-Mail Removed)> wrote:

> IMHO one of the most beautiful things about C is that it allows you
> such flexibility. It does not assume you are a baby and hold your
> hand.


Well, some would disagree with you, but then again, some are bad C
programmers

> I will continue to return pointers to static arrays in time sensitive
> functions because I am, and those who work under me are, smart enough
> to know what we're doing. =)


I don't have experience on embedded platforms (it sounds like you are
working on one), but from other posts to this group it seems that
dynamic memory rather than static memory is most at a premium. If you
have limited automatic storage, and you do this sort of thing
frequently, you might think about using a global union rather than
several static arrays; that could save you some more space.

--
C. Benson Manica | I *should* know what I'm talking about - if I
cbmanica(at)gmail.com | don't, I need to know. Flames welcome.
 
Reply With Quote
 
Dave Dunfield
Guest
Posts: n/a
 
      07-27-2006
> It seems pretty common to return pointers to a static array, for
>example:


>char *capitalize( char *name )
>{
> static char buf[MAX_STRING_LENGTH];


> sprintf( buf, "%s", name );
> if ( *buf >= 'a' && *buf <= 'z' )
> *buf += 'A' - 'a';


> return buf;
>}


> But when I do something like this, I like to instead keep a static
>pointer and malloc it the first time, to save space in whatever bank
>static memory is stored in, since I have this vague idea that if too
>much space is used in static memory bad things will happen? So I do
>this instead:


>char *capitalize( char *name )
>{
> static char *buf;


> if ( !buf )
> {
> buf = malloc( MAX_STRING_LENGTH );
> if ( !buf ) return name;
> }


> sprintf( buf, "%s", name );
> if ( *buf >= 'a' && *buf <= 'z' )
> *buf += 'A' - 'a';


> return buf;
>}


>Here is how I analyze both methods as far as efficiency:


>* the 2nd version uses less space in delicate "static memory" (not sure
>what that's called)
>* the 1st is much faster on the first call
>* the 1st is slightly faster the other calls (assuming the first time,
>malloc worked)
>* the 1st does not assume the OS will do appropriate cleanup on exit,
>as the 2nd does
>* the 1st is quicker to type


>I wonder which method is really best. I suppose it depends on how big
>MAX_STRING_LENGTH is. I assume for instance one wouldn't want to
>casually declare multi-hundred-kilobyte static arrays?


I prefer the first form (Assuming the size of memory you are allocating is
not huge - in which case you need to manage it much better than either
scenario), because:

- You are assuming there is more memory available on the heap than is
available during program initialization (which may well be allocated from
the system heap) - Unless you have information about the specific system
and run time environment (which makes it not a C question), this is probably
not a valid assumption.

- You never release the dynamically allocated memory, so assuming the
program eventually executes all of it's functions, your memory requirements
will be the same (in fact slightly higher because...):

- There is overhead in using the heap, block headers etc. which slightly
increase the memory usage for the heap based solution.

- Each malloc results in a allocation block on the heap, possibly fragmenting
memory (interleaved mallocs could be occuring within the same or a different
program. The static allocations will be resolved at compile/link time and
will (likely) occur within a single block which is organized and allocated at
program startup.

- Allocating from the heap takes cycles, testing that it has been allocated
also takes cycles (on each call).

- In this particular example, a shortage of memory will cause the program to
begin to behave erraticaly {capitalize() stops working}. Better to either
have the program fail to load if there is insufficient memory, or provide
better fault handling.

- As you pointed out, this is "untidy" in that the program does not free
the memory.

- Someone else mentioned the unsuitability of static memory in certain
concurrent processing applications, however your static pointer will
not resolve that problem. This isn't really an issue relating to the
question that was asked, as the runtime environment was not specified.

Regards,
Dave


--
Dunfield Development Services http://www.dunfield.com
Low cost software development tools for embedded systems
Software/firmware development services Fax:613-256-5821

 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      07-27-2006
Snis Pilbor wrote:

> Hi,
>
> It seems pretty common to return pointers to a static array, for
> example:
>
> char *capitalize( char *name )
> {
> static char buf[MAX_STRING_LENGTH];
>
> sprintf( buf, "%s", name );
> if ( *buf >= 'a' && *buf <= 'z' )
> *buf += 'A' - 'a';
>
> return buf;
> }


As an aside, this code has some problems. You'll be in
trouble if `name' has more than MAX_STRING_LENGTH-1 characters
(which means the macro name is a bit misleading), sprintf() is
a silly way to do strcpy(), and the manipulation of letter
case is badly misguided -- use toupper() instead.

> But when I do something like this, I like to instead keep a static
> pointer and malloc it the first time, to save space in whatever bank
> static memory is stored in, since I have this vague idea that if too
> much space is used in static memory bad things will happen? So I do
> this instead:
>
> char *capitalize( char *name )
> {
> static char *buf;
>
> if ( !buf )
> {
> buf = malloc( MAX_STRING_LENGTH );
> if ( !buf ) return name;


Whoa, Nellie! If returning the unmodified original is an
acceptable outcome, why bother writing the function at all?

> }
>
> sprintf( buf, "%s", name );
> if ( *buf >= 'a' && *buf <= 'z' )
> *buf += 'A' - 'a';
>
> return buf;
> }
>
> Here is how I analyze both methods as far as efficiency:
>
> * the 2nd version uses less space in delicate "static memory" (not sure
> what that's called)


It probably uses less if sizeof(char*) < MAX_STRING_LENGTH.
On the other hand, it uses more total space. The relative
"delicacy" of static and dynamic memory can only be assessed
in relation to the platform you're coding for; it's not a matter
the language itself describes at all.

> * the 1st is much faster on the first call


Probably -- although, again, speed is not a language issue,
but a characteristic of the platform.

> * the 1st is slightly faster the other calls (assuming the first time,
> malloc worked)


I see no compelling reason to think so.

> * the 1st does not assume the OS will do appropriate cleanup on exit,
> as the 2nd does
> * the 1st is quicker to type


You've overlooked a few other points. For example, both
versions hang onto their buffers even if they'll never be called
again, but the second could be modified to release it when called
with a NULL argument, say, if the program can figure out that
it won't be needed again.

> I wonder which method is really best. I suppose it depends on how big
> MAX_STRING_LENGTH is. I assume for instance one wouldn't want to
> casually declare multi-hundred-kilobyte static arrays?


"Best" depends on your purposes, and on the constraints and
opportunities presented by the implementation. That means there's
no universal answer; there is no best way to define "best." The
practice of engineering is all about reconciling competing goals;
it is unlikely the same answer will be chosen every time.

That said, practical considerations suggest that really large
static allocations are dubious. They were the life and breath of
large FORTRAN programs, but C is not FORTRAN.

--
Eric Sosman
(E-Mail Removed)lid
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      07-27-2006
Snis Pilbor wrote:
> Hi,
>
> It seems pretty common to return pointers to a static array, for
> example:
>
> char *capitalize( char *name )
> {
> static char buf[MAX_STRING_LENGTH];
>
> sprintf( buf, "%s", name );
> if ( *buf >= 'a' && *buf <= 'z' )
> *buf += 'A' - 'a';
>
> return buf;
> }
>
> But when I do something like this, I like to instead keep a static
> pointer and malloc it the first time, to save space in whatever bank
> static memory is stored in, since I have this vague idea that if too
> much space is used in static memory bad things will happen? So I do
> this instead:
>
> char *capitalize( char *name )
> {
> static char *buf;
>
> if ( !buf )
> {
> buf = malloc( MAX_STRING_LENGTH );
> if ( !buf ) return name;
> }
>
> sprintf( buf, "%s", name );
> if ( *buf >= 'a' && *buf <= 'z' )
> *buf += 'A' - 'a';
>
> return buf;
> }
>
> Here is how I analyze both methods as far as efficiency:
>

How about a third option:

char* capitalise( const char* name, char* buff, size_t buffLen );

Then you can choose whether to pass a dynamic or static buffer. This is
also one way to make this thread safe.


--
Ian Collins.
 
Reply With Quote
 
John L
Guest
Posts: n/a
 
      07-27-2006

"Snis Pilbor" <(E-Mail Removed)> wrote in message news:(E-Mail Removed) ps.com...
>
> EventHelix.com wrote:
> > Snis Pilbor wrote:
> > > Hi,
> > >
> > > It seems pretty common to return pointers to a static array, for
> > > example:
> > >
> > > char *capitalize( char *name )
> > > {
> > > static char buf[MAX_STRING_LENGTH];
> > >
> > > sprintf( buf, "%s", name );
> > > if ( *buf >= 'a' && *buf <= 'z' )
> > > *buf += 'A' - 'a';
> > >
> > > return buf;
> > > }

> >
> > IMHO, Use of static variables inside functions is not a good idea. You
> > will end up with code that is not thread safe. The function will
> > misbehave if multiple concurrently running threads are invoking the
> > function with static variables.
> >

>
> Yes, of course, it goes without saying in either case one must exercise
> caution.
> IMHO one of the most beautiful things about C is that it allows you
> such flexibility. It does not assume you are a baby and hold your
> hand.
> If I wanted a language where various people told me "Oh you can't do
> that, it's too dangerous", I would program Java =) Thanks for the word
> of warning anyway, though.
> I will continue to return pointers to static arrays in time sensitive
> functions because I am, and those who work under me are, smart enough
> to know what we're doing. =)
>


And also smart enough to remember that MAX_STRING_LENGTH does
not really mean "maximum string length" because the string needs to be
terminated, and smart enough to remember to fix (or at least check)
the code which changes letters to upper-case when it needs to cope with
languages (and alphabets) other than English, and smart enough to ensure
that the Human Resources Department never recruits anyone less smart
than you! Good luck.

--
John.


 
Reply With Quote
 
Richard Tobin
Guest
Posts: n/a
 
      07-27-2006
In article <(E-Mail Removed) .com>,
Snis Pilbor <(E-Mail Removed)> wrote:

> static char buf[MAX_STRING_LENGTH];


....

> if ( !buf )
> {
> buf = malloc( MAX_STRING_LENGTH );
> if ( !buf ) return name;
> }


>* the 2nd version uses less space in delicate "static memory" (not sure
>what that's called)


Why is static memory "delicate"?

>* the 1st is much faster on the first call


I cannot imagine any circumstance where the time taken by a single
malloc is significant.

>* the 1st is slightly faster the other calls (assuming the first time,
>malloc worked)


The time for the test is bound to be negligible compared with thet
sprintf.

>* the 1st does not assume the OS will do appropriate cleanup on exit,
>as the 2nd does


It assumes it will clear up static memory.

>* the 1st is quicker to type


How many times are you going to write it?

>I wonder which method is really best. I suppose it depends on how big
>MAX_STRING_LENGTH is. I assume for instance one wouldn't want to
>casually declare multi-hundred-kilobyte static arrays?


This is the most significant difference: if the function is not called
at all, the malloc version won't allocate any memory. But even this
may well be irrelevant on modern operating systems where zero-filled
memory is not allocated until it is used.

-- Richard

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
good algorithms come with practice and reading good code/books? vlsidesign C Programming 26 01-02-2007 09:50 AM
Good slide scanning service vs. good slide scanner for Do-It-Yourself? LAshooter Digital Photography 0 06-25-2005 07:14 AM
Signs are good, but WAN no good =?Utf-8?B?bmV0bnV0?= Wireless Networking 2 08-21-2004 12:41 PM
JLO situation+ why fastglass is good+DSLR is good Hugo Drax Digital Photography 0 01-17-2004 11:41 PM
Not even a newbee. Good at school course. please advise good start sikka noel C++ 8 08-05-2003 06:43 AM



Advertisments