Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Q: Local variables initialization shortcut.

Reply
Thread Tools

Q: Local variables initialization shortcut.

 
 
BartC
Guest
Posts: n/a
 
      06-02-2012
"BartC" <(E-Mail Removed)> wrote in message news:jqcu41$oa0$(E-Mail Removed)...
> "Jean-Christophe" <(E-Mail Removed)> wrote in message


>> I'm translating an existing source code into C language so


> You mentioned Windows elsewhere. If you're only interested in one
> particular
> platform (eg. x86) and don't care about portability, perhaps consider a
> bit
> of inline assembler. This can look at the frame and stack pointers, and do
> a block clear of the memory in between.


I should add this might not be portable across compilers either. Especially
gcc, which might just decide to eliminate the frame pointer completely. But
then it also makes it more difficult to use inline asm anyway.

--
Bartc

 
Reply With Quote
 
 
 
 
Jens Thoms Toerring
Guest
Posts: n/a
 
      06-02-2012
Jean-Christophe <(E-Mail Removed)> wrote:
> On 2 juin, 12:31, (E-Mail Removed) :
> > Finally not on all systems a 0.0 value
> > is represented by all bits set to zero.


> Well, at least this is the case for
> Windows float and double, isn't it ?


Probably, since all hardware on Windows seem to be using
the very common IEEE 754 format for floating points. But
that isn't something required by the C standard, some sys-
tems may use a different bit representation for floating
points.

> > '&z - &a' isn't legal - you can only subtract addresses
> > of locations within a single object (e.g. an array),


> I've done it many times and it always worked fine :
> &a is the address of 'a' so it's its memory location.


Well, you were lucky. The standard doesn't define what
the result of subtracting pointers not within the same
object is (or, in the case of arrays, one beyond the
end of the array), so you are relying on whatever your
compiler makes out of it. Some other compiler might
give you a different result.

> Except for this actual example (when variables are stored
> in stack w/ their adresses allocated by the compiler)


There also is no requirement for a stack in the C stan-
dard. Most (or probably all) compilers will employ
something stack-like for local variables, but that is
a decision the compiler writer makes, not something
prescribed by the standard.

> if the location of 'a' thru 'z' are well stored
> (i.e, like in an array) then the following code works fine :
> unsigned int size = (unsigned int)( &z - &a );


Yes, it may seem to work on your system with the specific
compiler you are using. If you want your program to work
only on that system and with that compiler then this is
probably all fine, just dont expect it to work anymore
under different circumstances.

> > everything else is undefined behaviour, And even if
> > disregarding this and assuming that 'a' is at the lowest
> > and 'z' at the highest address, '&z - &a' will be the
> > number of variable between 'a' and 'z' (25) and not the
> > number of bytes used in between, so you would have to
> > multiply by the size of a double.


> Hum, no : if &z is the highest address
> and &a is the lowest address then (&z - &a)
> is the number of bytes (less one sizeof) and not the
> number of variables (unless 'a' and 'z' are chars)


That may well be the case. Since you are relying on un-
defined behaviour everything you get is "right". Just for
the fun of it: on my system (x86-64 Linux and with gcc)
the output of this program

#include <stdio.h>
int main( void )
{
double a, b;
printf( "%d\n", ( int ) ( &a - &b ) );
return 0;
}

is -1. So obviously at least some of the deductions you
were led to make by the behaviour on your system aren't
valid from what I see on my machine. And that's quite
ok since the behaviour of that program isn't defined,
so whatever the output is is correct. (And I have de-
finitely worked with machines were variables defined
later had lower addresses).

For even more giggles take this program:

#include <stdio.h>
int main( void )
{
double a, b, c;
printf( "%d\n", ( int ) ( &a - &c ) );
return 0;
}

The output on my machine is still -1...

But I am a bit puzzled - I would expect the difference
between two pointers of the same type to be number of
variables of that type in between, not the number of
bytes. Otherwise the behaviour (while undefined) would
be even more weird on your machine since e.g. for
arrays you can rely on the difference between the
addresses of two of its elements to be the number of
elements in between. But then, again, the moment you
do something undefined everything can happen.

> > Since you try to treat these variables (at least in the
> > respect of initialization) as if they make up an array,
> > would it be possible to atually use an array? Then ini-
> > tialization is rather simple:
> > double a2z[ 26 ] = { 0.0 };


> Yes of course, but the problem is that these
> variables names are not as simple as 'a'...'z'
> and they are used individually (am I clear here ?)
> So then, to use your suggestion I should do something like


> // declare & init


> #define VAR_THIS d[0]
> #define VAR_THAT d[1]
> #define VAR_SOMETHING d[2]
> ... etc ...
> #define VAR_MAX 10 // for instance


> double d[VAR_MAX];
> memset( d, 0, VAR_MAX * sizeof(d[0]) );


> // using variables


> VAR_THIS = ... ;
> VAR_THAT = ... ;
> x = ... VAR_THIS ... VAR_THAT ... ;


> ... but then, to write the whole set
> of #define looks a bit heavy to me !


Of course, this is the probably even worse than
writing

a = b = c = .... = z = 0.0;

since it's much harder to understand. The only conclusion
is that what you want to do can't be done in a portable
fashion in C.
Refards, Jens
--
\ Jens Thoms Toerring ___ http://www.velocityreviews.com/forums/(E-Mail Removed)
\__________________________ http://toerring.de
 
Reply With Quote
 
 
 
 
Jean-Christophe
Guest
Posts: n/a
 
      06-02-2012
On 2 juin, 13:40, "BartC" :

> Actually, if you are using doubles, then it doesn't necessarily follow that
> it will be much slower to clear these one-by-one, compared with, say, 8 or
> 16-bit variables. (It's possible also it might be faster, if the compiler
> would otherwise use a loop.) Have you done any measurements?


The speed is not an issue here.
The point is to reset to zero all these variables,
while keeping their original names.


> Do the variables need to be cleared on every call to the function?


Yes.


> If they only need to be cleared once, then using static variables
> will ensure they are 0.0 at the start of execution
> (at least, on most hardware).


Nah, can't be static.


> Also, does *every* variable need to start at zero?
> Some, surely, must have a different starting value,
> perhaps set by an assignment.


Yes.


> (In which case, a compiler might optimise out the 0.0
> initialisation; but it means you don't need to clear it first.)


That's right, but the original code is a real mess,
for debug purpose I need al least to set all variables to zero
otherwise I won't even know whose values are (in)correct.


> You mentioned Windows elsewhere. If you're only interested in one particular
> platform (eg. x86) and don't care about portability,


Yes, this is the case.


> perhaps consider a bit of inline assembler.
> This can look at the frame and stack pointers, and do a
> block clear of the memory in between. Although this will indiscriminately
> zero all local variables, including ones you want initialised to something
> else. (They need initialising by assignment instead.)


Hum, sounds a bit tricky to me.
Thanks for the idea anyway.
 
Reply With Quote
 
Jean-Christophe
Guest
Posts: n/a
 
      06-02-2012
On 2 juin, 14:03, pete :

> If you beieve that something which works once,
> will always work again,


I didn't meant that.

> then why ask questions
> instead of just testing your code?


Because I need advice.

> The C standard characterizes that operation as being undefined.
> N1570
> 6.5.6 Additive operators
> 9 When two pointers are subtracted,
> both shall point to elements of the same array object,
> or one past the last element of the array object;
> the result is the difference of the
> subscripts of the two array elements.


Good enough for me, thanks.
 
Reply With Quote
 
Jean-Christophe
Guest
Posts: n/a
 
      06-02-2012
On 2 juin, 13:55, (E-Mail Removed) (Jens Thoms Toerring) wrote:

> > > Finally not on all systems a 0.0 value
> > > is represented by all bits set to zero.

> > Well, at least this is the case for
> > Windows float and double, isn't it ?

> Probably, since all hardware on Windows seem to be using
> the very common IEEE 754 format for floating points. But
> that isn't something required by the C standard, some sys-
> tems may use a different bit representation for floating
> points.


Ok.


> > > '&z - &a' isn't legal - you can only subtract addresses
> > > of locations within a single object (e.g. an array),

> > I've done it many times and it always worked fine :
> > &a is the address of 'a' so it's its memory location.

> Well, you were lucky. The standard doesn't define what
> the result of subtracting pointers not within the same
> object is (or, in the case of arrays, one beyond the
> end of the array), so you are relying on whatever your
> compiler makes out of it. Some other compiler might
> give you a different result.


Ok, I'll remember that.


> > Except for this actual example (when variables are stored
> > in stack w/ their adresses allocated by the compiler)

> There also is no requirement for a stack in the C stan-
> dard. Most (or probably all) compilers will employ
> something stack-like for local variables, but that is
> a decision the compiler writer makes, not something
> prescribed by the standard.


Ok.


> > if the location of 'a' thru 'z' are well stored
> > (i.e, like in an array) then the following code works fine :
> > unsigned int size = (unsigned int)( &z - &a );

> Yes, it may seem to work on your system with the specific
> compiler you are using. If you want your program to work
> only on that system and with that compiler then this is
> probably all fine, just dont expect it to work anymore
> under different circumstances.


Right. This is clumsy.


> > if &z is the highest address
> > and &a is the lowest address then (&z - &a)
> > is the number of bytes (less one sizeof) and not the
> > number of variables (unless 'a' and 'z' are chars)

> That may well be the case. Since you are relying on un-
> defined behaviour everything you get is "right". Just for
> the fun of it: on my system (x86-64 Linux and with gcc)
> the output of this program
> #include <stdio.h>
> int main( void )
> { double a, b;
> printf( "%d\n", ( int ) ( &a - &b ) );
> return 0;
> }
> is -1. So obviously at least some of the deductions you
> were led to make by the behaviour on your system aren't
> valid from what I see on my machine. And that's quite
> ok since the behaviour of that program isn't defined,
> so whatever the output is is correct. (And I have de-
> finitely worked with machines were variables defined
> later had lower addresses).
> For even more giggles take this program:
> #include <stdio.h>
> int main( void )
> { double a, b, c;
> printf( "%d\n", ( int ) ( &a - &c ) );
> return 0;
> }
> The output on my machine is still -1...
> But I am a bit puzzled - I would expect the difference
> between two pointers of the same type to be number of
> variables of that type in between, not the number of
> bytes.


You are right because you're talking about *pointers* :
int i;
double d1, d2, *a, *b;
a = &d1;
b = &d2;
i = (int)( b - a ); // assuming &d2 > &d1
then i == 1 // number of variables
because it's a difference of pointers
of a given variable type.

This is a different matter than :
int i;
double d1, d2;
i = (int)( &d2 - &d1 ); // assuming &d2 > &d1
then i == sizeof(double) // number of bytes
because it's a difference of addresses
whatever the variable type is.


> > ... but then, to write the whole set
> > of #define looks a bit heavy to me !

> Of course, this is the probably even worse than writing
> a = b = c = .... = z = 0.0;
> since it's much harder to understand. The only conclusion
> is that what you want to do can't be done in a portable
> fashion in C.


All right then.
I understand I made the error of expanding my knowledge
of 'micro-controllers' C compilers to the 'PC' C compilers.
Some things won't work at all, and if they do
it's even worse because it's just luck.

Thanks for taking time.
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      06-02-2012
On 6/2/2012 7:55 AM, Jens Thoms Toerring wrote:
> Jean-Christophe<(E-Mail Removed)> wrote:
>> [...]
>>> '&z -&a' isn't legal - you can only subtract addresses
>>> of locations within a single object (e.g. an array),

>
>> I've done it many times and it always worked fine :
>> &a is the address of 'a' so it's its memory location.

>
> Well, you were lucky. The standard doesn't define what
> the result of subtracting pointers not within the same
> object is (or, in the case of arrays, one beyond the
> end of the array), so you are relying on whatever your
> compiler makes out of it. Some other compiler might
> give you a different result.


As a concrete example not requiring "exotic" hardware,
consider this fragment:

char buff[15];
typedef char Blob[7];
Blob *b1 = (Blob*) &buff[0];
Blob* b2 = (Blob*) &buff[8];

Now, what is `b2 - b1'? Pointer subtraction is supposed to
yield the number of pointed-at things between the two positions,
but how many 7-byte Blobs fit in the 8 bytes between their
starting positions? (For extra credit, change `8' to `1' in
the final line and answer again.)

In other words, the requirement is even stronger than Jens'
informal statement of it: You can only subtract pointers within
an array *of the pointed-at type*. The fact that `b1' and `b2'
both aim at spots within the array `buff' is not enough.

--
Eric Sosman
(E-Mail Removed)d
 
Reply With Quote
 
Jean-Christophe
Guest
Posts: n/a
 
      06-02-2012
My apologies :

#include <stdio.h>
int main(void)
{
double a,b;
printf( "&b - &a = %2d\r\n", (int)( &b - &a ) );
printf( "&a - &b = %2d\r\n", (int)( &a - &b ) );
return 0;
}

&b - &a = 1
&a - &b = -1
 
Reply With Quote
 
Jean-Christophe
Guest
Posts: n/a
 
      06-02-2012
Sorry about the misunderstanding,
this is what I meant :

#include <stdio.h>
double a,b;
int main(void)
{
unsigned int ia = (unsigned int)&a;
unsigned int ib = (unsigned int)&b;
printf( "ib - ia = %u\r\n", ib - ia );
printf( "ia - ib = %u\r\n", ia - ib );
return 0;
}


ib - ia = 8 // = sizeof(double)
ia - ib = 4294967288 // crap

 
Reply With Quote
 
BartC
Guest
Posts: n/a
 
      06-02-2012
"Jean-Christophe" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On 2 juin, 13:40, "BartC" :
>
>> Actually, if you are using doubles, then it doesn't necessarily follow
>> that
>> it will be much slower to clear these one-by-one, compared with, say, 8
>> or
>> 16-bit variables. (It's possible also it might be faster, if the compiler
>> would otherwise use a loop.) Have you done any measurements?

>
> The speed is not an issue here.
> The point is to reset to zero all these variables,
> while keeping their original names.


Perhaps I'm missing the point somewhere, but in that case, what's wrong
with:

double a=0.0, b=0.0, .... ?

Do you just want to save some typing?

> perhaps consider a bit of inline assembler.
>> This can look at the frame and stack pointers, and do a
>> block clear of the memory in between.


> Hum, sounds a bit tricky to me.
> Thanks for the idea anyway.


Yeah, forget that. You need to be on intimate terms with your compiler to
try things like that.

--
Bartc



 
Reply With Quote
 
Jean-Christophe
Guest
Posts: n/a
 
      06-02-2012
On 2 juin, 15:00, "BartC" :

> Perhaps I'm missing the point somewhere,
> but in that case, what's wrong with:
> double a=0.0, b=0.0, .... ?
> Do you just want to save some typing?


I'm re-writing a messy 7500 lines source code into C,
I kept all the same variables names to ease debugging
and there are a LOT of functions, each one with its
own LOT of local variables - all having different names.
At least I want to initialise all of them to zero to
avoid uninitialized variables ****-up (if I may say so)

So it won't save me 'some' typing: I'll save a 'lot' of typing.


> > perhaps consider a bit of inline assembler.
> >> This can look at the frame and stack pointers, and do a
> >> block clear of the memory in between.

> > Hum, sounds a bit tricky to me.
> > Thanks for the idea anyway.


> Yeah, forget that. You need to be on intimate
> terms with your compiler to try things like that.


Sure. Thanks Bartc.

 
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
initialization order of function local static variables Severin Ecker C++ 9 03-11-2010 11:41 PM
local static variables' default initialization auspicious C++ 0 09-25-2008 10:02 PM
Can local function access local variables in main program? Sullivan WxPyQtKinter Python 10 11-08-2007 02:51 PM
different handling of local variables and instance variables when undefined Tammo Tjarks Ruby 2 09-13-2007 06:29 PM
Local variables initialization Michal Kwiatkowski Python 5 02-27-2006 02:56 AM



Advertisments