468,463 Members | 2,030 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,463 developers. It's quick & easy.

Is this a good habit?

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 =)

Jul 27 '06 #1
62 3593

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

Jul 27 '06 #2

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

Jul 27 '06 #3
Snis Pilbor <sn********@yahoo.comwrote:
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.
Jul 27 '06 #4
Snis Pilbor (in 11*********************@i3g2000cwc.googlegroups.co 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
Jul 27 '06 #5
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
es*****@acm-dot-org.invalid
Jul 27 '06 #6
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

Jul 27 '06 #7
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.
Jul 27 '06 #8

"Snis Pilbor" <sn********@yahoo.comwrote in message news:11*********************@i3g2000cwc.googlegrou 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.
Jul 27 '06 #9
In article <11**********************@h48g2000cwc.googlegroups .com>,
Snis Pilbor <sn********@yahoo.comwrote:
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

Jul 27 '06 #10
In article <28******************************@magma.ca>,
Dave Dunfield <Da***********@use.techsupport.link.on.my.websitew rote:
>- 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.
Unless you don't use malloc() (or something that calls it, perhaps
printf()) anywhere else, this may well just change where the run-time
failure occurs.

-- Richard
Jul 27 '06 #11
>- 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.
>Unless you don't use malloc() (or something that calls it, perhaps
printf()) anywhere else, this may well just change where the run-time
failure occurs.
Assuming you do not handle potential failures of malloc
correctly in these "anywhere else" locations....

I cannot comment on the possible other uses of malloc, only
the case shown in the example,, which causes an undetected
change in operation if malloc fails.

Cheers.
Dave

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

Jul 27 '06 #12

uninitialized static memory is, in most C implementations, not emitted
as a long array of zeroes, but just as a note to the linker or C
sraretup code to add xxx bytes to the zero-initialized "BSS" segment.
So these variables do not make the executable file any longer.

Agin, in most C implementations, the BSS area is just taken off the top
of the free memory pool and doesnt impact on the size of anything
else-- EXCEPT if you're using an old 16-bit compiler, generating 16-bit
segments-- there you probably will be limited to 65536 bytes of total
static data.

I'd be more concerned about the sprintf() overflowing the array! That
could be really baad!

Jul 27 '06 #13
Ancient_Hacker said:
>
uninitialized static memory is, in most C implementations,
Translation: most of those you've encountered.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jul 27 '06 #14
On Wed, 26 Jul 2006 19:22:43 -0700, 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.
And worse, to my mind, is that with either version
printf( "%s %s\n", capitalise( "bob"), capitalise( "mary"));
will be disappointing.
Jul 27 '06 #15

Richard Heathfield wrote:
Ancient_Hacker said:

uninitialized static memory is, in most C implementations,

Translation: most of those you've encountered.

Okay, how's about you compile this little program and tell us the size
of the obj and executable files:

int a[1000000];

int main( int argc, char * argv[] ) {

a[1] = 99;
printf("%d\n", A[1] );
return 0;
}

I would LOVE to learn what C compilers are so poorly conceived as to
emit uninitialized static data as initialized data.

I've probably had the acquaintance of a dozen C compilers over the
centuries, and I don't recall a one that was quite this clunky. I'd
love to learn of counterexamples.

Jul 27 '06 #16
Ancient_Hacker wrote:
>
Richard Heathfield wrote:
>Ancient_Hacker said:
>
uninitialized static memory is, in most C implementations,

Translation: most of those you've encountered.


Okay, how's about you compile this little program and tell us the size
of the obj and executable files:

int a[1000000];

int main( int argc, char * argv[] ) {

a[1] = 99;
printf("%d\n", A[1] );
return 0;
}

I would LOVE to learn what C compilers are so poorly conceived as to
emit uninitialized static data as initialized data.
I /think/ early versions of Norcroft C under RISC OS did that, but my
memory may be misfiring.

--
Chris "nortalgic" Dollin
"People are part of the design. It's dangerous to forget that." /Star Cops/

Jul 27 '06 #17
Snis Pilbor posted:
* the 1st does not assume the OS will do appropriate cleanup on exit,
as the 2nd does

void *p; /* Global variable */

void DelDynam(void)
{
free(p);
}
Then inside you function:

if ( !p )
{
p = malloc( MAX_STRING_LENGTH );
if ( !p ) return name;

atexit(DelDynam);
}

--

Frederick Gotham
Jul 27 '06 #18
Ancient_Hacker said:
>
Richard Heathfield wrote:
>Ancient_Hacker said:
>
uninitialized static memory is, in most C implementations,

Translation: most of those you've encountered.


Okay, how's about you compile this little program and tell us the size
of the obj and executable files:

int a[1000000];
Stop right there. No implementation is obliged to support an object that
size.

<snip>

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jul 27 '06 #19
On Thu, 27 Jul 2006 13:46:21 +0000, Frederick Gotham wrote:
Snis Pilbor posted:
>* the 1st does not assume the OS will do appropriate cleanup on exit,
as the 2nd does


void *p; /* Global variable */

void DelDynam(void)
{
free(p);
}
Then inside you function:

if ( !p )
{
p = malloc( MAX_STRING_LENGTH );
if ( !p ) return name;

atexit(DelDynam);
}
I don't want to sound like a nitpick, but this will fail if atexit() fails
(it returns 0 on success and non-0 on failure), so you might want inform
the user if this happens.
I personally don't bother with atexit() and do all cleanup myself.
Jul 27 '06 #20

Ancient_Hacker wrote:
Richard Heathfield wrote:
Ancient_Hacker said:
>
uninitialized static memory is, in most C implementations,
Translation: most of those you've encountered.


Okay, how's about you compile this little program and tell us the size
of the obj and executable files:

int a[1000000];

int main( int argc, char * argv[] ) {

a[1] = 99;
printf("%d\n", A[1] );
return 0;
}
ERROR CCN3045 T9232EH.SOURCE.C(AC):6 Undeclared identifier A.

WARNING CCN3304 T9232EH.SOURCE.C(AC):6 No function prototype given
for "printf".

INFORMATIONAL CCN3410 T9232EH.SOURCE.C(AC):8 The automatic variable
"A" is defined but never referenced.

INFORMATIONAL CCN3414 T9232EH.SOURCE.C(AC):8 The parameter "argv"
is never referenced.

INFORMATIONAL CCN3414 T9232EH.SOURCE.C(AC):8 The parameter "argc"
is never referenced.

CCN0793(I) Compilation failed for file //'T9232EH.SOURCE.C(AC)'.
Object file not created.

Jul 27 '06 #21

Richard Heathfield wrote:
int a[1000000];

Stop right there. No implementation is obliged to support an object that
size.
Thanks once again for the disengenuous comeback.

One might surmise that you know the purpose, or actually, purposes of
my typing 1 million in that spot.

(1) If the compiler has a 16-bit restriction on array sizes, we learn
of it right away.

(2) if the compiler accepts it, and the linker does too, then we know
this is most likely a 32-bit address space or wider system. That's
useful info in and of itself.

(3) If the object and exe files are a few tens of K larger than 2 or 4
or 8 meg, then we've learned that this C system is really lame, at
least under the4 default compile/link options. If the object and exe
files are much much smaller than 1 meg, typically a few tens of
kilobytes, then we've learned the original poster need not worry too
much about uninitialized static variables. If we'd chosen a much
smaller number, such as 1000, then it would be hard to tell just from
the size of the files how the C system handled uninitialized variables.

Jul 27 '06 #22

Jalapeno wrote:
ERROR CCN3045 T9232EH.SOURCE.C(AC):6 Undeclared identifier A.

WARNING CCN3304 T9232EH.SOURCE.C(AC):6 No function prototype given
for "printf".

INFORMATIONAL CCN3410 T9232EH.SOURCE.C(AC):8 The automatic variable
"A" is defined but never referenced.

INFORMATIONAL CCN3414 T9232EH.SOURCE.C(AC):8 The parameter "argv"
is never referenced.

INFORMATIONAL CCN3414 T9232EH.SOURCE.C(AC):8 The parameter "argc"
is never referenced.

CCN0793(I) Compilation failed for file //'T9232EH.SOURCE.C(AC)'.
Object file not created.

How about you try again, after making the trivial and all so obvious
changes?

Jul 27 '06 #23
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:

* the 2nd version uses less space in delicate "static memory" (not sure
what that's called)
Only until it is 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'd generally go with the first method (if forced too, at gunpoint
by the people holding my salary check hostage) because I work
with embedded systems and would rather have the application not
load at all than load and fail with a memory error (which tends
to confuse the poor user).

The first way, I know in advance that I'm exceeding my memory
constraints. The second way could load just fine but the testers
might not ever execute an action that could cause the malloc,
and I won't know that I'm out of memory until 20000 devices are
in the field and the *user* executes it.

That said, if I were free to chhose, I would write this function
like so:

int capitalise (char *dst, char *src);

This way I can seperate the functions functionality
from the memory management and be able to return an
error value independent of the return string i.e.
I could return any one of a couple of #defined error
values instead of only NULL.

goose,

Jul 27 '06 #24
Snis Pilbor wrote:
EventHelix.com wrote:
Snis Pilbor wrote:
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.
What the hell is *WRONG* with you people. Review what EventHelix is
saying. If you need to run in a multithreaded environment then static
solution *CANNOT WORK*. Let me repeat: *CANNOT WORK*.

So you take this piece of information and you go on some diatribe about
how you are so grateful for the fact that C lets you code things that
in some contexts *CANNOT WORK*?
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. =)
Really? Unless the static is read-only, or you are in the module
containing main(), I would never do this -- because I figure I am
"smart enough" to know better. If you want to avoid the allocation
costs, then you can *pass in* the buffers you want to be used -- in
that way you retain the performance, and there is no multithreading
issue. Its a question of scalability -- if you need to think hard
about every piece of code you use (in this case knowing that you can't
use the function while multithreading), then that's time and energy
taken away from thinking hard about other programming details, like
architecture/design.

I'm not sure this occurred to K&R (and T) when they originally designed
C and Unix (the counter evidence in the std library seems overwhelming)
but what you should celebrate is that they don't *force* you to make
this kind of mistake. I guess its a moot point since you *are* making
the mistake anyways.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/

Jul 27 '06 #25
Ancient_Hacker wrote:
Jalapeno wrote:
ERROR CCN3045 T9232EH.SOURCE.C(AC):6 Undeclared identifier A.

WARNING CCN3304 T9232EH.SOURCE.C(AC):6 No function prototype given
for "printf".

INFORMATIONAL CCN3410 T9232EH.SOURCE.C(AC):8 The automatic variable
"A" is defined but never referenced.

INFORMATIONAL CCN3414 T9232EH.SOURCE.C(AC):8 The parameter "argv"
is never referenced.

INFORMATIONAL CCN3414 T9232EH.SOURCE.C(AC):8 The parameter "argc"
is never referenced.

CCN0793(I) Compilation failed for file //'T9232EH.SOURCE.C(AC)'.
Object file not created.


How about you try again, after making the trivial and all so obvious
changes?
Sure, how about posting compilable code if you want us to compile it.

5694A01 V1 R6 z/OS C 'T9232EH.SOURCE.C(AC)'
E X T E R N A L S Y M B O L D I C T I O N A R Y
NAME TYPE ID ADDR LENGTH
PC 1 000000 000108
MAIN LD 0 000018 000001
PRINTF ER 4 000000
CEEMAIN SD 6 000000 00000C
MAIN ER 8 000000

A SD 2 000000 3D0900 <--<< lookee
CEESG003 ER 3 000000
CEESTART ER 5 000000
EDCINPL ER 7 000000

* * * * * E N D O F C O M P I L A T I O N

z/OS V1 R6 BINDER 10:47:28 THURSDAY JULY 27, 2006

BATCH EMULATOR JOB(T9232EHA) STEP(STEP1) PGM=IEWL PROCEDURE(LKED)
IEW2278I B352 INVOCATION PARAMETERS - AMODE=31,MAP

*** M O D U L E M A P ***

---------------

CLASS B_TEXT
LENGTH = 3D1402 <--<< lookee
ATTRIBUTES = CAT,
LOAD, RMODE=ANY
OFFSET = 0 IN SEGMENT 001 ALIGN = DBLWORD
---------------
SECTION CLASS ------- SOURCE --------
OFFSET OFFSET NAME TYPE LENGTH DDNAME SEQ MEMBER

0 CEESTART CSECT 7C SYSLIN 01 **NULL**

80 $PRIV000010 CSECT 108 SYSLIN 01 **NULL**
18 98 MAIN LABEL

lookee >>-- 188 A CSECT 3D0900 SYSLIN 01 **NULL**

3D0A88 CEEMAIN CSECT C SYSLIN 01 **NULL**

3D0A98 CEESG003 * CSECT 12B SYSLIB 01 CEESG003

3D0BC8 EDCINPL * CSECT 24 SYSLIB 01 EDCINPL

3D0BF0 PRINTF * CSECT A SYSLIB 01 PRINTF

3D0C00 CEEROOTA * CSECT 1F0 SYSLIB 01 CEEROOTA
0 3D0C00 CEEROOTD LABEL

3D0DF0 CEEBETBL * CSECT 28 SYSLIB 01 CEEBETBL

3D0E18 CEEBPUBT * CSECT 70 SYSLIB 01 CEEBPUBT

3D0E88 CEEBTRM * CSECT A4 SYSLIB 01 CEEBTRM

3D0F30 CEEBLLST * CSECT 5C SYSLIB 01 CEEBLLST
10 3D0F40 CEELLIST LABEL

3D0F90 CEEBINT * CSECT 8 SYSLIB 01 CEEBINT

3D0F98 CEEARLU * CSECT B0 SYSLIB 01 CEEARLU

3D1048 CEEBPIRA * CSECT 2D8 SYSLIB 01 CEEINT
0 3D1048 CEEINT LABEL
0 3D1048 CEEBPIRB LABEL
0 3D1048 CEEBPIRC LABEL

3D1320 CEECPYRT * CSECT E2 SYSLIB 01 CEEINT

SAVE OPERATION SUMMARY:

MEMBER NAME GO
LOAD LIBRARY SYS06208.T104725.RA000.T9232EHA.GOSET.H01
PROGRAM TYPE LOAD MODULE
VOLUME SERIAL
MAX BLOCK 32760
DISPOSITION ADDED NEW
TIME OF SAVE 10.47.29 JUL 27, 2006
SAVE MODULE ATTRIBUTES:

AC 000
AMODE 31
DC NO
EDITABLE YES
EXCEEDS 16MB NO
EXECUTABLE YES
MIGRATABLE YES
OL NO
OVLY NO
PACK,PRIME NO,NO
PAGE ALIGN NO
REFR NO
RENT NO
REUS NO
RMODE ANY
SCTR NO
SSI
SYM GENERATED NO
TEST NO
XPLINK NO
MODULE SIZE (HEX) 003D1408 <--<< lookee


Menu Functions Confirm Utilities Help
--------------------------------------------------------------------
VIEW T9232EH.Z.LOAD Row 00001 of 00003
Command === Scroll ===CSR
Name Prompt Alias-of Size TTR AC AM RM
_________ AC 003D1408 000016 00 31 ANY
**End**
/ \
|
lookee ----------------------------+
I think perhaps you should be asking questions in this newsgroup
instead of answering them.

Jul 27 '06 #26

In article <11*********************@75g2000cwc.googlegroups.c om>, "Ancient_Hacker" <gr**@comcast.netwrites:
Richard Heathfield wrote:
Ancient_Hacker said:
uninitialized static memory is, in most C implementations,
Translation: most of those you've encountered.

Okay, how's about you compile this little program and tell us the size
of the obj and executable files:
How breathtakingly irrelevant. Not, apparently, an ancient
rhetorician, in any event.
I've probably had the acquaintance of a dozen C compilers over the
centuries, and I don't recall a one that was quite this clunky.
I'm sorry, but this isn't clear. Are you claiming that "a dozen C
compilers" constitutes "most C implementations", or are you admitting
that Richard was correct?

--
Michael Wojcik mi************@microfocus.com

Unlikely prediction o' the day:
Eventually, every programmer will have to write a Java or distributed
object program.
-- Orfali and Harkey, _Client / Server Programming with Java and CORBA_
Jul 27 '06 #27
Ancient_Hacker wrote:
Richard Heathfield wrote:
Ancient_Hacker said:
uninitialized static memory is, in most C implementations,
Translation: most of those you've encountered.

Okay, how's about you compile this little program and tell us the size
of the obj and executable files:

int a[1000000];
int main( int argc, char * argv[] ) {
a[1] = 99;
printf("%d\n", A[1] );
return 0;
}

I would LOVE to learn what C compilers are so poorly conceived as to
emit uninitialized static data as initialized data.
Actually a utility called "CauseWay", which is a DOS extender and
linker for WATCOM C/C++ would expand out the BSS segment to the
sequence of zeros at link time. While this seems like an insane thing
to do, it was a moot point, because their linker also comes with an
exe-compressor which detects and squashes these segments down to
nothing anyways. Its actually only an issue with compile times, since
the linker has to generate these big spaces, then the compressor has to
squash them back down.
I've probably had the acquaintance of a dozen C compilers over the
centuries, and I don't recall a one that was quite this clunky. I'd
love to learn of counterexamples.
Well, as I point out above -- the issue is with the *linker* and
compiler.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/

Jul 27 '06 #28
I think perhaps you should be asking questions in this newsgroup
instead of answering them.

Sigh. And I think you should be following the suggestions above,
instead of printing out irrelevant link maps.

I suggested you show us the size of the obj and exe files. Surely your
system has a "dir"-like command?

The numbers shown on the link map are irrelevant. Of course the
lengths are going to be correct, they couldnt be otherwise. The
question is, did the compiler and linker emit four or eight million
zeroes, or did they emit "reserve 4000000 bytes".

Even if your particular compiler/linker are so brain-damaged as to
write out megabytes of zeroes, that doesnt impact the original poster's
question, as it's unlikely his embedded application runs or will ever
run on a IBM mainframe.

Jul 27 '06 #29

Michael Wojcik wrote:

I'm sorry, but this isn't clear. Are you claiming that "a dozen C
compilers" constitutes "most C implementations",
We've been over this before. I've been saddled with using C since the
very early days, so it's been my misfortune to intimately know Unix V6
C, Venix C, Mark Williams C, a 1979 Intel C (urp), Microsoft and
Borland C's since versions 1.0, Convergent C, and so on and bloodily
so forth thru early Sun, SGI, HP/UX, AIX, and other C's. I don't
recall a one that emitted long chunks of zeroes when it didnt have to.
And as others have mentioned, even that isnt a sure way to determine if
the executable is going to be bloated, thanks to exe compressors. And
even that doesnt tell us what the poor original poster wanted to know.


or are you admitting
that Richard was correct?

--
Michael Wojcik mi************@microfocus.com

Unlikely prediction o' the day:
Eventually, every programmer will have to write a Java or distributed
object program.
-- Orfali and Harkey, _Client / Server Programming with Java and CORBA_
Jul 27 '06 #30
"Ancient_Hacker" <gr**@comcast.netwrites:
Jalapeno wrote:
>ERROR CCN3045 T9232EH.SOURCE.C(AC):6 Undeclared identifier A.

WARNING CCN3304 T9232EH.SOURCE.C(AC):6 No function prototype given
for "printf".

INFORMATIONAL CCN3410 T9232EH.SOURCE.C(AC):8 The automatic variable
"A" is defined but never referenced.

INFORMATIONAL CCN3414 T9232EH.SOURCE.C(AC):8 The parameter "argv"
is never referenced.

INFORMATIONAL CCN3414 T9232EH.SOURCE.C(AC):8 The parameter "argc"
is never referenced.

CCN0793(I) Compilation failed for file //'T9232EH.SOURCE.C(AC)'.
Object file not created.

How about you try again, after making the trivial and all so obvious
changes?
How about you post compilable code in the first place, rather than
insisting that others do your work for you? If you can't be bothered
to take the time to compile your own code yourself before posting, I
certainly can't be bothered to fix it.

Yes, turning what you posted into something compilable is nearly
trivial. So take the time to do it yourself. We'll be glad to point
out your errors, but we're not here to fix them for you (unless
perhaps the errors are the point of a post, which these weren't).

In any case, a single example compiled on a single implementation
doesn't really prove anything. Upthread, you wrote:

| uninitialized static memory is, in most C implementations, not emitted
| as a long array of zeroes, but just as a note to the linker or C
| sraretup code to add xxx bytes to the zero-initialized "BSS" segment.
| So these variables do not make the executable file any longer.

and Richard quite correctly replied:

| Translation: most of those you've encountered.

It may well also be true of most, or even all, C implementations that
Richard has encountered, or that I've encountered. We may or may not
be able to come up with an implementation that doesn't behave the way
you described (though I seriously doubt that all implementation have
something called a "BSS segment"). The point is that we discuss the
*language* here, not (mostly) specific implementations of it. If you
want to talk about BSS segments and other things that are not defined
by the C language (and that, where they exist, are not C-specific),
there are places to do so.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jul 27 '06 #31
we******@gmail.com writes:
[...]
What the hell is *WRONG* with you people. Review what EventHelix is
saying. If you need to run in a multithreaded environment then static
solution *CANNOT WORK*. Let me repeat: *CANNOT WORK*.

So you take this piece of information and you go on some diatribe about
how you are so grateful for the fact that C lets you code things that
in some contexts *CANNOT WORK*?
Stop shouting.

Not all code needs to worry about being used in a multithreading
environment.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jul 27 '06 #32
Ancient_Hacker wrote:
Michael Wojcik wrote:

>I'm sorry, but this isn't clear. Are you claiming that "a dozen C
compilers" constitutes "most C implementations",

We've been over this before. I've been saddled with using C since the
very early days, so it's been my misfortune to intimately know Unix V6
C, Venix C, Mark Williams C, a 1979 Intel C (urp), Microsoft and
Borland C's since versions 1.0, Convergent C, and so on and bloodily
so forth thru early Sun, SGI, HP/UX, AIX, and other C's.
Yes, you've made that claim before. with reference to how to write a
macro that behaved like sizeof. All the macros you provided broke on the
compilers I have easy access to even *after* you corrected a problem.
I don't
recall a one that emitted long chunks of zeroes when it didnt have to.
And as others have mentioned, even that isnt a sure way to determine if
the executable is going to be bloated, thanks to exe compressors. And
even that doesnt tell us what the poor original poster wanted to know.
You suggested lots of things that are not necessarily true. For example
suggesting that the size of the bss section will not be limited and
won't affect other things. Well, I've news for you, on Linux limits can
be set for the size of the bss section and for the total memory of a
process. If you are not the administrator of the box you won't be able
to change any global limits that have been set up.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Jul 27 '06 #33

Flash Gordon wrote:
Ancient_Hacker wrote:
Michael Wojcik wrote:

I'm sorry, but this isn't clear. Are you claiming that "a dozen C
compilers" constitutes "most C implementations",
We've been over this before. I've been saddled with using C since the
very early days, so it's been my misfortune to intimately know Unix V6
C, Venix C, Mark Williams C, a 1979 Intel C (urp), Microsoft and
Borland C's since versions 1.0, Convergent C, and so on and bloodily
so forth thru early Sun, SGI, HP/UX, AIX, and other C's.

Yes, you've made that claim before. with reference to how to write a
macro that behaved like sizeof. All the macros you provided broke on the
compilers I have easy access to even *after* you corrected a problem.
Sorry to hear you were unable to see the very obvious fix of putting
(char *) before each pointer. Also sorry to see you tend to hang onto
old grudges that were'nt worth grumbling about in the first place.

You suggested lots of things that are not necessarily true. For example
suggesting that the size of the bss section will not be limited and
won't affect other things.
Sorry to see you have trouble with reading and comprehension, not to
mention simple logic and analysis. The fella was talking about an
embedded application, so administrator-set limits are not a problem, as
he *is* the administrator, plus unlikely to be running Linux on that
wristwatch or whatnot.. And he was inquiring about like 80 byte
arrays, not your typical multi-megabyte admin limits. And our test was
mainly to see if there was a 16-bit limit. You may remember the
horrible 80's and 90's when most of us were always slamming against a
16-bit limit or another. Once past that limit, its mostly clear
sailing.

Jul 27 '06 #34
In article <11*********************@b28g2000cwb.googlegroups. com>
Ancient_Hacker <gr**@comcast.netwrote:
>We've been over this before. I've been saddled with using C since the
very early days, so it's been my misfortune to intimately know Unix V6
C, Venix C, Mark Williams C, a 1979 Intel C (urp), Microsoft and
Borland C's since versions 1.0, Convergent C, and so on and bloodily
so forth thru early Sun, SGI, HP/UX, AIX, and other C's. I don't
recall a one that emitted long chunks of zeroes when it didnt have to.
I do.

(In a similar, but not quite identical, case, the VMS C compiler used
to turn:

switch (x) {
case 0: zerostuff(); break;
case 32767: maxstuff(); break;
default: general(); break;
}

into a whopping executable with every possible value in 0..32767
actually enumerated.)
>And as others have mentioned, even that isnt a sure way to determine if
the executable is going to be bloated, thanks to exe compressors.
Indeed. (I believe ARM had an interesting paging-specific compressed
binary format.)

The point is, you have made unsupported claims, and incorrect claims,
and then complained about the fact that people have pointed out that
they are unsupported and/or incorrect.

(Some of your unsupported claims are, in my experience, true. That
does not make them supported. You could avoid a lot of problems by
adding "in my experience" or similar weasel-words; or, in this
particular case, you could simply have said that one should try
to avoid implementations that generate poor code and/or executables,
since there is now usually a choice here.)
--
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.
Jul 27 '06 #35

Chris Torek wrote:
In article <11*********************@b28g2000cwb.googlegroups. com>
Ancient_Hacker <gr**@comcast.netwrote:
I don't
recall a one that emitted long chunks of zeroes when it didnt have to.

I do.
No, you don't. Otherwise you would have mentioned it. What you diod
instead is give an example of something completely different:
>>
(In a similar, but not quite identical, case, the VMS C compiler used
to turn:

switch (x) {
case 0: zerostuff(); break;
case 32767: maxstuff(); break;
default: general(); break;
}

into a whopping executable with every possible value in 0..32767
actually enumerated.)
hat case has nothing to do with BSS storage. In your case the compiler
had to generate INITIALIZED data, either a table of jump addresses, or
a table of jump instructions. In either case, that's nothing like
uninitialized storage. Yes, it's an examlpe of a compiler doing a dumb
thing. In that case the compiler should have chosen to generate soem
if tests, or a short table of value/address pairs, only two entries
long. But it's not in any way what we were discussing. So thanks for
the verification, neither one of us has seen a compiler that generates
all those zeroes instead of a simple BSS.

And as others have mentioned, even that isnt a sure way to determine if
the executable is going to be bloated, thanks to exe compressors.
That's why I carefully specified that one should print out the length
of *both* the object file and the executable.

The point is, you have made unsupported claims, and incorrect claims.
Please feel free to start straightening me out. Any time now.

,
and then complained about the fact that people have pointed out that
they are unsupported and/or incorrect.
I do get a bit miffed by folks that are consistently intellectually
dishonest.
Some people go to great lengths to ignore reality and hold to very
narrow views. I've found those attitudes to be unhelpful.

(Some of your unsupported claims are, in my experience, true. That
does not make them supported.
What the H*ll does that mean? If they're true in your experience, how
can that not be support? Sounds like a very fine distinction.

You could avoid a lot of problems by
adding "in my experience" or similar weasel-words;

How could anything be NOT "in my experience"?
or, in this
particular case, you could simply have said that one should try
to avoid implementations that generate poor code and/or executables,
since there is now usually a choice here.)
I'm not into begging the question or stating the obvious.
I will let the original poster judge whose comments were more apt.

Jul 27 '06 #36

we******@gmail.com wrote:
Well, as I point out above -- the issue is with the *linker* and
compiler.
Worse than that-- it depends on the two, plus on the actions of the
usual "cl" launcher that runs the two and passes and mangles options
between them, plus it dfepends on options the options passed to one or
both, plus as someone mentioned, there were exe-packer programs
especially made to post-fix these bloated exe files. Not to mention
some frugal OS's has program loaders that knew about exe files with
allocation holes in them. Lots of possible interactions. Can we
discuss something simpler like brain surgery?

Jul 27 '06 #37
On 27 Jul 2006 10:37:19 -0700, in comp.lang.c , "Ancient_Hacker"
<gr**@comcast.netwrote:
>
>I think perhaps you should be asking questions in this newsgroup
instead of answering them.


Sigh. And I think you should be following the suggestions above,
instead of printing out irrelevant link maps.

I suggested you show us the size of the obj and exe files.
Apparently you're unfamiliar with mainframe OSen. Heck, even on a Vax
(which aint no mainframe) the size of the executable on disk was
irrelevant, and rounded to the nearest 512 to boot.

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jul 27 '06 #38
On 27 Jul 2006 13:12:48 -0700, in comp.lang.c , "Ancient_Hacker"
<gr**@comcast.netwrote:
>
Flash Gordon wrote:
>Yes, you've made that claim before. with reference to how to write a
macro that behaved like sizeof. All the macros you provided broke on the
compilers I have easy access to even *after* you corrected a problem.

Sorry to hear you were unable to see the very obvious fix of putting
(char *) before each pointer.
So lets get this straight: /you/ wrote broken buggy code which failed
to do what you claimed, and somehow thats someone else's fault.

Theres a pretty important rule round here: post correct code, or
expect to get ripped to shreds.
>Sorry to see you have trouble with reading and comprehension, not to
mention simple logic and analysis.
And being abusive to regulars won't help you either.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jul 27 '06 #39

Mark McIntyre wrote:
On 27 Jul 2006 10:37:19 -0700, in comp.lang.c , "Ancient_Hacker"
<gr**@comcast.netwrote:
I think perhaps you should be asking questions in this newsgroup
instead of answering them.

Sigh. And I think you should be following the suggestions above,
instead of printing out irrelevant link maps.

I suggested you show us the size of the obj and exe files.

Apparently you're unfamiliar with mainframe OSen. Heck, even on a Vax
(which aint no mainframe) the size of the executable on disk was
irrelevant, and rounded to the nearest 512 to boot.
I'd consider CDC 6600's, 7600's, Vax 11/780's (Which was definitely a
mainframe, at least in size) as "mainframes". I don't know what you
mean about the size of the executable being irrelevant. We were trying
to determine whether uninitialized static data was written out as a run
of zeroes. That point is not irrelevant to the original poster, indeed
it was the nub of his crux.

And the biz about "rounded" is pointless-- most OS's allocate files by
the block. That has nothing at all to do with the subject under
discussion. And the "nearest" 512? makes it kinda hard to run half
the programs.
>
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jul 27 '06 #40
On 27 Jul 2006 14:27:32 -0700, in comp.lang.c , "Ancient_Hacker"
<gr**@comcast.netwrote:
>
Chris Torek wrote:
>In article <11*********************@b28g2000cwb.googlegroups. com>
Ancient_Hacker <gr**@comcast.netwrote:
I don't
>recall a one that emitted long chunks of zeroes when it didnt have to.

I do.

No, you don't. Otherwise you would have mentioned it. What you diod
instead is give an example of something completely different:
Excellent, so now you are attacking one of /the/ most respected
posters here. Top marks for idiocy.

Expect to get rapidly plonked by those with short fuses, and your
every post watched like a hawk by those with a strong sense of duty to
the newbies, who do not deserve to be fed misinformation.
>hat case has nothing to do with BSS storage. In your case the compiler
had to generate INITIALIZED data,
You were claiming that no compiler would be so stupid as to fail to
make obvious optimisations. Chris (and others) have produced
counterexamples of even more obvious optimisations that got missed.

For what its worth, I recall one of the earlier MSC implementations
(possibly 5.1) did indeed insert zero-initialised storage into the
binary. After all, if it had been part-initialised to nonzeros then
creating it from scratch could have been expensive at runtime.

>The point is, you have made unsupported claims, and incorrect claims.

Please feel free to start straightening me out. Any time now.
Its happening.
>and then complained about the fact that people have pointed out that
they are unsupported and/or incorrect.

I do get a bit miffed by folks that are consistently intellectually
dishonest.
Do you find yourself doing Travis Bickle impersonations a lot?
>Some people go to great lengths to ignore reality and hold to very
narrow views. I've found those attitudes to be unhelpful.
Indeed.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jul 27 '06 #41

Mark McIntyre wrote:
On 27 Jul 2006 14:27:32 -0700, in comp.lang.c , "Ancient_Hacker"
<gr**@comcast.netwrote:

Chris Torek wrote:
In article <11*********************@b28g2000cwb.googlegroups. com>
Ancient_Hacker <gr**@comcast.netwrote:
hat case has nothing to do with BSS storage. In your case the compiler
had to generate INITIALIZED data,

You were claiming that no compiler would be so stupid as to fail to
make obvious optimisations. Chris (and others) have produced
counterexamples of even more obvious optimisations that got missed.
Uh, no. First of all, incrementing a BSS counter to allocate
uninitialized data is about the only rational way to do it. It's not
an optimization. And I said no such thing. It's hard to be a
revisionist historian when the original words are jsut a click away.

Chris's example, while interesting in a theoretical and historical
sense, has nothing at all to do with what we were discussing. case
tables are initialized data, or code-- not anything we were discussing
at all. And optimizing that is not obvious, I recall the UCSD
compiler had the same inefficiency, (until I fixed it so it would
generate value/jmp address pair tables when appropriate).

For what its worth, I recall one of the earlier MSC implementations
(possibly 5.1) did indeed insert zero-initialised storage into the
binary. After all, if it had been part-initialised to nonzeros then
creating it from scratch could have been expensive at runtime.
You're still not getting the big distinction between initialized data
and uninitialized data. The former has to be pretty much emitted as is
(with some obvious compressions possible). global variables that do
not have the "= something" business are a whole different kettle of
fish. All the compiler has to do is define a label and bump a BSS
size variable.

For a little more insight-- the whole BSS segment business goes back to
the IBM 7090 days, when memory cost a dollar a word or more. There was
no place for the system loader to sit when loading a big program, so
some smart fellow suggested that assemblers and compilers explicitly
point out what areas of memory did not have to be initialized. The
loader would relocate itself into that space and merrily load the
program code and data around it. Nowadays we have the luxury of lots
of memory so BSS space isnt that crucial as it once was, but it still
helps cut down the size of executables.

Jul 27 '06 #42
Ancient_Hacker said:
>
Richard Heathfield wrote:
int a[1000000];

Stop right there. No implementation is obliged to support an object that
size.

Thanks once again for the disengenuous comeback.
Nothing disingenuous about it at all. You posted a program that the C spec
doesn't require an implementation to be able to support.
One might surmise that you know the purpose, or actually, purposes of
my typing 1 million in that spot.
Presumably you were trying to write an invalid program. You succeeded on
several counts. I merely identified the first problem.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jul 27 '06 #43
Keith Thompson said:

<snip>
>
Not all code needs to worry about being used in a multithreading
environment.
Nevertheless, avoiding static objects is a reasonable rule of thumb, unles
they're also const.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jul 27 '06 #44
Richard Heathfield <in*****@invalid.invalidwrites:
Keith Thompson said:
<snip>
>>
Not all code needs to worry about being used in a multithreading
environment.

Nevertheless, avoiding static objects is a reasonable rule of thumb, unles
they're also const.
Agreed.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jul 27 '06 #45
>In article <11*********************@b28g2000cwb.googlegroups. com>
>Ancient_Hacker <gr**@comcast.netwrote:
>>I don't recall a one [C compiler, including pre-ANSI] that emitted
long chunks of zeroes when it didnt have to.
>Chris Torek wrote:
>I do.
In article <11**********************@s13g2000cwa.googlegroups .com>,
Ancient_Hacker <gr**@comcast.netwrote:
>No, you don't. Otherwise you would have mentioned it.
What on earth makes you think that? It is hardly relevant, since
it is no longer a useful C compiler and was never ANSI-conformant.

(In any case, I take it you never used Turbo C.)

You might also look at:

http://www.digitalmars.com/d/archive...2-bits/38.html

(where Walter Bright does say that this is a bug, not a feature;
and of course this is C++, not C).
>What you did instead is give an example of something completely
different:
Not *completely* different at all -- just another case of a compiler
doing something stupid.
--
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.
Jul 28 '06 #46

we******@gmail.com wrote:
Snis Pilbor wrote:
EventHelix.com wrote:
Snis Pilbor wrote:
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.

What the hell is *WRONG* with you people. Review what EventHelix is
saying. If you need to run in a multithreaded environment then static
solution *CANNOT WORK*. Let me repeat: *CANNOT WORK*.

So you take this piece of information and you go on some diatribe about
how you are so grateful for the fact that C lets you code things that
in some contexts *CANNOT WORK*?
Of course it can work, and it works correctly in many programs. It
cannot work if more than one thread need to concurrently do the quantum
of 'call the function and use the results'. If the design of the
program prevents that happening, or if an associated mutex is required
to be held before using the function, then it works correctly.

Whether it's the best or optimum way to do it is another question, and
I'd almost always say it's not. But as Snis says, C has the flexibility
to allow it to be done this way if it is appropriate for whatever
reason. Most of the times I've found it appropriate are when a library
of such code already exists, and its functionality is now needed in a
limited and controlled way in a threaded program.
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. =)

Really? Unless the static is read-only, or you are in the module
containing main(), I would never do this -- because I figure I am
"smart enough" to know better.
So you would do it sometimes even though it *CANNOT WORK*?
If you want to avoid the allocation
costs, then you can *pass in* the buffers you want to be used -- in
that way you retain the performance, and there is no multithreading
issue. Its a question of scalability -- if you need to think hard
about every piece of code you use (in this case knowing that you can't
use the function while multithreading), then that's time and energy
taken away from thinking hard about other programming details, like
architecture/design.
Indeed, and that's the main issue to trade off in my opinion. C gives
you the flexibility to do it the static way if the advantages are big
enough.
I'm not sure this occurred to K&R (and T) when they originally designed
C and Unix (the counter evidence in the std library seems overwhelming)
but what you should celebrate is that they don't *force* you to make
this kind of mistake. I guess its a moot point since you *are* making
the mistake anyways.
The original C model didn't have the concept of multiple threads in a
single address space, since it was based on the original UNIX concept
of forked processes with private address space.

Jul 28 '06 #47
J. J. Farrell wrote:
we******@gmail.com wrote:
>>What the hell is *WRONG* with you people. Review what EventHelix is
saying. If you need to run in a multithreaded environment then static
solution *CANNOT WORK*. Let me repeat: *CANNOT WORK*.

So you take this piece of information and you go on some diatribe about
how you are so grateful for the fact that C lets you code things that
in some contexts *CANNOT WORK*?
C and quite a bit of most networking libraries based on the original BSD
interface.
>
Of course it can work, and it works correctly in many programs. It
cannot work if more than one thread need to concurrently do the quantum
of 'call the function and use the results'. If the design of the
program prevents that happening, or if an associated mutex is required
to be held before using the function, then it works correctly.
>>I'm not sure this occurred to K&R (and T) when they originally designed
C and Unix (the counter evidence in the std library seems overwhelming)
but what you should celebrate is that they don't *force* you to make
this kind of mistake. I guess its a moot point since you *are* making
the mistake anyways.


The original C model didn't have the concept of multiple threads in a
single address space, since it was based on the original UNIX concept
of forked processes with private address space.
The same problem exists with the UNIX standard library functions that
use internal static buffers.

Even today, people still use these calls even though they have been
superseded by thread safe replacements.

--
Ian Collins.
Jul 28 '06 #48
Chris Torek wrote:
Indeed. (I believe ARM had an interesting paging-specific compressed
binary format.)
I don't know if this is what you're thinking of, but RISC OS (hence on the
ARM) did indeed have a executable file format that as it loaded (or
perhaps after it had loaded) it uncompressed code from the file. The win
was of course that it could uncompress much faster than it could load
from disc (and it made the disc files smaller, a not inconsiderable gain
in those days).

I don't remember it being paging-specific, though. Maybe that was on
ARM Linux.

--
Chris "nostalgic, but not for the CLI" Dollin
"We did not have time to find out everything we wanted to know." /A Clash of Cymbals/

Jul 28 '06 #49

Eric Sosman wrote:
Snis Pilbor wrote:
[snip]
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?
That said, it's the most graceful handling of a failed malloc that I
have seen for a long time. It depends what your priorities are.

Jul 28 '06 #50

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

12 posts views Thread by Arlie Rahn | last post: by
39 posts views Thread by Suresh | last post: by
45 posts views Thread by Brett | last post: by
5 posts views Thread by Phil Jones | last post: by
9 posts views Thread by Jake Montgomery | last post: by
reply views Thread by NPC403 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.