static array initialization

M

mdh

Hi all,

When I try and initialize this static array, as in:

void itoa_recursively(int n, char *s){
static char *p = s;

it fails, yet this:


void itoa_recursively(int n, char *s){
static char *p;
p = s;

succeeds.

the error is "Initializer error is not constant". If I change the
declaration to "const char *s", this does not work either and declare
the parameter of the function as a constant, it also fails.


Thanks
 
H

Harald van Dijk

Hi all,

When I try and initialize this static array, as in:

void itoa_recursively(int n, char *s){
static char *p = s;

it fails,

Well, yes. You tell the compiler you want to initialise p at the start of
the program, and the initial value will be provided as a function
argument. That doesn't make sense; the function argument won't exist until
the program is already running. Why are you using static? What is it
you're trying to do?
 
M

mdh

. Why are you using static? What is it
you're trying to do?


Here is the full code, which succeeds. I need to ( I think) keep track
of which index is being assigned to (in s), hence the static. But, I
could be wrong. I adapted this from 4-12, in Tondo and Gimpel, who use
an idex, and not a pointer.


#include <stdlib.h>

void itoa_recursively(int n, char *s){
static char *p;
p = s;

if ( n / 10 )
itoa_recursively(n / 10, s);
else
if ( n < 0)
*p++ = '-';
*p++ = abs(n) % 10 + '0';
*p = '\0';
}
 
S

S James S Stapleton

#include <stdlib.h>

void itoa_recursively(int n, char *s){
static char *p;
p = s;

'static' means every call of the function uses the same variable. So, when
you set p=s, every prior call will have p equal to the new value, s.

I think I see a few bugs in your program, but I could be wrong. In general,
if you are trying to do what I think you are trying to do, p shouldn't be
static, that doesn't provide any benefit, and introduces a lot of extra
required logic and potential for bugs.

-Jim
 
H

Harald van Dijk

. Why are you using static? What is it

Here is the full code, which succeeds. I need to ( I think) keep track
of which index is being assigned to (in s), hence the static.

Alright, then yes, if you write the function the way you have now, you do
need static.
But, I
could be wrong. I adapted this from 4-12, in Tondo and Gimpel, who use
an idex, and not a pointer.

#include <stdlib.h>

void itoa_recursively(int n, char *s){
static char *p;
p = s;

if ( n / 10 )
itoa_recursively(n / 10, s);
else
if ( n < 0)
*p++ = '-';
*p++ = abs(n) % 10 + '0';
*p = '\0';
}

When you call

itoa_recursively(10, buf1)

and you then later call

itoa_recursively(10, buf2)

do you want to change p to point to buf2? You probably should, which means
the "initialization" of p needs to be performed every time you call your
function. Initialisation (as in static char *p = ...;) will only be
performed when p is created, and since it is only created once, it would
never be changed to buf2 even if you hadn't got an error back from the
compiler. To change a variable after its creation, use an assignment.
That's what you're doing now. That's what you should continue to do.
 
H

Harald van Dijk

'static' means every call of the function uses the same variable. So,
when you set p=s, every prior call will have p equal to the new value,
s.

I think I see a few bugs in your program, but I could be wrong. In
general, if you are trying to do what I think you are trying to do, p
shouldn't be static, that doesn't provide any benefit, and introduces a
lot of extra required logic and potential for bugs.

The way itoa_recursively is written is strange, but it's written
correctly. p needs to be static:

itoa_recursively(123, &buf[0])
- p = &buf[0]
- call itoa_recursively(12, &buf[0])
- p = &buf[0]
- call itoa_recursively(1, &buf[0])
- p = &buf[0]
- buf[0] = '1'
- buf[1] = '\0'
- p = &buf[1]
*** - buf[1] = '2'
- buf[2] = '\0'
- p = &buf[2]
*** buf[2] = '3'
- buf[3] = '\0'
- p = &buf[3]
- return

The two lines I marked with *** rely on p having kept its value from the
recursion. Without it, the outer call would effectively store the string
"3" in buf, and nothing more.
 
S

S James S Stapleton

I think I see a few bugs in your program, but I could be wrong. In
general, if you are trying to do what I think you are trying to do, p
shouldn't be static,

I followed the logic wrong, the Harold's response is correct. P should be
static the way you are doing things.

-Jim Stapleton
 
M

mdh

The two lines I marked with *** rely on p having kept its value from the
recursion. Without it, the outer call would effectively store the string
"3" in buf, and nothing more.

Thanks Harald
 
C

CBFalconer

mdh said:
When I try and initialize this static array, as in:

void itoa_recursively(int n, char *s){
static char *p = s;

it fails, yet this:

void itoa_recursively(int n, char *s){
static char *p;
p = s;

succeeds.

the error is "Initializer error is not constant". If I change
the declaration to "const char *s", this does not work either
and declare the parameter of the function as a constant, it
also fails.

Try removing the 'static'. It is totally foolish when you are
initializing the object on function entry. Also realize that a
'const' object is not a compile time constant. In C, it is a
read-only object, and can only be set in an initialization
statement.
 
M

mdh

Try removing the 'static'.  It is totally foolish when you are
initializing the object on function entry.  Also realize that a
'const' object is not a compile time constant.  In C, it is a
read-only object, and can only be set in an initialization
statement.

Hmmm...OK?
But, I thought a static internal variable retains it's value between
iterations, which I am trying to do, as I need to know where to add
the next digit. Or...I might be totally misunderstanding the rule
about static. It does seem to work this way though, probably by blind
luck.
 
C

CBFalconer

mdh said:
Hmmm...OK? But, I thought a static internal variable retains
it's value between iterations, which I am trying to do, as I
need to know where to add the next digit. Or...I might be
totally misunderstanding the rule about static. It does seem to
work this way though, probably by blind luck.

But you are not using that retained value, you are reinitializing
it at function entry (IIRC - there is no quote on your reply, and
you have also purged the attribution lines).
 
K

Keith Thompson

mdh, I'm confused about "It does seem to work this way though" since
as I recall the code, you're trying to initialize a static with
a non-constant, so it should not even compile. (At least not in C,
it will compile in C++, and will pick up the first parameter even
passed in the first iteration). The assignment version is another story.

I think he's saying that the version where he uses an assignment
rather than an initializer seems to work.
 
M

mdh

But you are not using that retained value, you are reinitializing
it at function entry .

Sorry..should have included that.


#include <stdlib.h>
void itoa_recursively(int n, char *s){
static char *p;
p = s;
if ( n / 10 )
itoa_recursively(n / 10, s);
else
if ( n < 0)
*p++ = '-';
*p++ = abs(n) % 10 + '0';
*p = '\0';
}

Well, here is my naive ( and incorrect) way of understanding this. I
**thought!!** that once the ptr *p is initialized, then subsequent
iterations through the function would be able to use the retained
information for placing the digits correctly in "s". I used Tondo and
Gimpel's answer to 4-12 as a basis for this. They declared a static
variable which was used to keep the information about the position of
the next digit to be added, as in:


#include <stdlib.h>
void itoa_recursively(int n, char *s){
static int i;

if ( n / 10 )
itoa_recursively(n / 10, s);
else
i = 0;
if ( n < 0)
s[i++] = '-';
s[i++] = abs(n) % 10 + '0';
s = '\0';
}
 
M

mdh

mdh, I'm confused about "It does seem to work this way though" since
as I recall the code, you're trying to initialize a static with
a non-constant, so it should not even compile. (At least not in C,
it will compile in C++, ........

I am using Xcode. No warnings. No failures the way I have it written.
 
M

mdh

I incorrectly copied the code for T&G earlier. I have corrected this
here.

But you are not using that retained value, you are reinitializing
it at function entry .


Sorry..should have included that.
#include <stdlib.h>
void itoa_recursively(int n, char *s){
static char *p;
p = s;
if ( n / 10 )
itoa_recursively(n / 10, s);
else
if ( n < 0)
*p++ = '-';
*p++ = abs(n) % 10 + '0';
*p = '\0';
}

Well, here is my naive ( and incorrect) way of understanding this. I
**thought!!** that once the ptr *p is initialized, then subsequent
iterations through the function would be able to use the retained
information for placing the digits correctly in "s". I used Tondo
and
Gimpel's answer to 4-12 as a basis for this. They declared a static
variable which was used to keep the information about the position of
the next digit to be added, as in:
#include <stdlib.h>
void itoa_recursively(int n, char *s){
static int i;
if ( n / 10 )
itoa_recursively(n / 10, s);
else {
i = 0;
if ( n < 0)
s[i++] = '-'; }
s[i++] = abs(n) % 10 + '0';
s = '\0';
 
K

Keith Thompson

mdh said:
Sorry..should have included that.
#include <stdlib.h>
void itoa_recursively(int n, char *s){
static char *p;
p = s;
if ( n / 10 )
itoa_recursively(n / 10, s);
else
if ( n < 0)
*p++ = '-';
*p++ = abs(n) % 10 + '0';
*p = '\0';
}

Well, here is my naive ( and incorrect) way of understanding this. I
**thought!!** that once the ptr *p is initialized, then subsequent
iterations through the function would be able to use the retained
information for placing the digits correctly in "s".

The only difference between a static variable defined inside a
function and one defined at file scope is visibility.

If you moved the declaration of ``p'' outside your function, making it
a global variable, but leaving the assignment "p = s;" where it is,
the behavior of your program would not change -- but it might be a
little easier to understand. The value you assign to p isn't
available within an inner recursive call. *But* the value assigned to
``p'' by your inner recursive call *is* available in the outer call.

With line numbers:

1 #include <stdlib.h>
2 void itoa_recursively(int n, char *s){
3 static char *p;
4 p = s;
5 if ( n / 10 )
6 itoa_recursively(n / 10, s);
7 else
8 if ( n < 0)
9 *p++ = '-';
10 *p++ = abs(n) % 10 + '0';
11 *p = '\0';
12 }

At line 4, you assign a value to ``p''. At line 6, you call
itoa_recursively(), assigning some new value to ``p''. At lines 10
and 11, the value of ``p'' isn't the value assigned at line 4, it's
the value assigned somewhere within the recursive call.

I'm too lazy to trace through the logic of your program, but it's not
obviously wrong.
I used Tondo and Gimpel's answer to 4-12 as a basis for this. They
declared a static variable which was used to keep the information
about the position of the next digit to be added, as in:
#include <stdlib.h>
void itoa_recursively(int n, char *s){
static int i;
if ( n / 10 )
itoa_recursively(n / 10, s);
else {
i = 0;
if ( n < 0)
s[i++] = '-'; }
s[i++] = abs(n) % 10 + '0';
s = '\0';


Note that T&G's version doesn't clobber the static variable every time
it enters the function. (I'm not saying it should or shouldn't.)
 
W

Willem

CBFalconer wrote:
) mdh wrote:
)> void itoa_recursively(int n, char *s){
)> static char *p;
)> p = s;
)
) Try removing the 'static'. It is totally foolish when you are
) initializing the object on function entry.

I beg to differ. Does the following seem foolish to you ?
It serves the same function as the 'static' used above.

void itoa_recursively(int n, char *s, char **p) {
*p = s;


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
M

mdh

#include <stdlib.h>
void itoa_recursively(int n, char *s){
        static int i;
        if ( n / 10 )
                itoa_recursively(n / 10, s);
        else {
i = 0;
if ( n < 0)
                        s[i++] = '-'; }
        s[i++] = abs(n) % 10 + '0';
        s = '\0';


Note that T&G's version doesn't clobber the static variable every time
it enters the function.  (I'm not saying it should or shouldn't.)


I guess I need to refine my understanding of a static internal
variable. On p 83 of k&r it says "Internal static variables are local
to a particular function.....but....they remain in existence rather
than coming and going each time the function is
activated. ....provide permanent storage within a single function."
Does this not mean that once one has called this function, that static
variable will hold onto it's value as long as one is running a program
that uses that function...or is this not the way to think about it?
 
B

Barry Schwarz

#include <stdlib.h>
void itoa_recursively(int n, char *s){
        static int i;
        if ( n / 10 )
                itoa_recursively(n / 10, s);
        else {
i = 0;
if ( n < 0)
                        s[i++] = '-'; }
        s[i++] = abs(n) % 10 + '0';
        s = '\0';


Note that T&G's version doesn't clobber the static variable every time
it enters the function.  (I'm not saying it should or shouldn't.)


I guess I need to refine my understanding of a static internal
variable. On p 83 of k&r it says "Internal static variables are local
to a particular function.....but....they remain in existence rather
than coming and going each time the function is
activated. ....provide permanent storage within a single function."
Does this not mean that once one has called this function, that static
variable will hold onto it's value as long as one is running a program
that uses that function...or is this not the way to think about it?


Perhaps I'm picking a non-existent nit but instead of "a program" I
think you need "the program". Also, the variable is created and
receives its initialization value prior to the function being called.
Here is what the standard says (6.2.4):

"An object whose identifier is declared with external or internal
linkage, or with the storage-class specifier static has static storage
duration. Its lifetime is the entire execution of the program and its
stored value is initialized only once, prior to program startup."


Remove del for email
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,197
Latest member
Sean29G025

Latest Threads

Top