Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #21648 > unrolled thread

Q: Local variables initialization shortcut.

Started byJean-Christophe <5.d@free.fr>
First post2012-06-02 02:49 -0700
Last post2012-06-02 17:50 +0000
Articles 20 on this page of 61 — 17 participants

Back to article view | Back to comp.lang.c


Contents

  Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 02:49 -0700
    Re: Q: Local variables initialization shortcut. China Blue Max <chine.bleu@yahoo.com> - 2012-06-02 03:03 -0700
      Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 03:17 -0700
    Re: Q: Local variables initialization shortcut. jacob navia <jacob@spamsink.net> - 2012-06-02 12:06 +0200
      Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 03:25 -0700
        Re: Q: Local variables initialization shortcut. James Kuyper <jameskuyper@verizon.net> - 2012-06-02 10:59 -0400
          Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 13:02 -0700
            Re: Q: Local variables initialization shortcut. Keith Thompson <kst-u@mib.org> - 2012-06-02 14:51 -0700
    Re: Q: Local variables initialization shortcut. Ian Collins <ian-news@hotmail.com> - 2012-06-02 22:10 +1200
    Re: Q: Local variables initialization shortcut. jt@toerring.de (Jens Thoms Toerring) - 2012-06-02 10:31 +0000
      Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 03:59 -0700
        Re: Q: Local variables initialization shortcut. jt@toerring.de (Jens Thoms Toerring) - 2012-06-02 11:55 +0000
          Re: Q: Local variables initialization shortcut. pete <pfiland@mindspring.com> - 2012-06-02 08:15 -0400
          Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 05:37 -0700
            Re: Q: Local variables initialization shortcut. jt@toerring.de (Jens Thoms Toerring) - 2012-06-02 13:35 +0000
              Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 06:47 -0700
                Re: Q: Local variables initialization shortcut. "BartC" <bc@freeuk.com> - 2012-06-02 15:08 +0100
                  Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 07:37 -0700
                    Re: Q: Local variables initialization shortcut. "BartC" <bc@freeuk.com> - 2012-06-02 16:17 +0100
                      Re: Q: Local variables initialization shortcut. "BartC" <bc@freeuk.com> - 2012-06-02 19:02 +0100
                Re: Q: Local variables initialization shortcut. jt@toerring.de (Jens Thoms Toerring) - 2012-06-02 17:39 +0000
                  Re: Q: Local variables initialization shortcut. Eric Sosman <esosman@ieee-dot-org.invalid> - 2012-06-02 15:27 -0400
                    Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 12:58 -0700
                      Re: Q: Local variables initialization shortcut. Eric Sosman <esosman@ieee-dot-org.invalid> - 2012-06-02 16:15 -0400
                    Re: Q: Local variables initialization shortcut. David Brown <david.brown@hesbynett.no> - 2012-06-03 15:27 -0500
                      Re: Q: Local variables initialization shortcut. Noob <root@localhost> - 2012-06-05 09:12 +0200
                        Re: Q: Local variables initialization shortcut. David Brown <david@westcontrol.removethisbit.com> - 2012-06-05 09:21 +0200
                  Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 12:53 -0700
                    Re: Q: Local variables initialization shortcut. "BartC" <bc@freeuk.com> - 2012-06-02 21:16 +0100
                    Re: Q: Local variables initialization shortcut. jt@toerring.de (Jens Thoms Toerring) - 2012-06-02 21:18 +0000
                      Re: Q: Local variables initialization shortcut. Eric Sosman <esosman@ieee-dot-org.invalid> - 2012-06-02 17:38 -0400
                        Re: Q: Local variables initialization shortcut. jt@toerring.de (Jens Thoms Toerring) - 2012-06-02 22:15 +0000
                        Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-03 00:51 -0700
                        Re: Q: Local variables initialization shortcut. Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-06-03 11:46 -0700
                      Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-03 00:13 -0700
                    Re: Q: Local variables initialization shortcut. Keith Thompson <kst-u@mib.org> - 2012-06-02 14:50 -0700
                    Re: Q: Local variables initialization shortcut. David Brown <david.brown@hesbynett.no> - 2012-06-03 15:34 -0500
            Re: Q: Local variables initialization shortcut. David Brown <david.brown@hesbynett.no> - 2012-06-03 15:25 -0500
          Re: Q: Local variables initialization shortcut. Eric Sosman <esosman@ieee-dot-org.invalid> - 2012-06-02 08:46 -0400
          Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 05:46 -0700
            Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 05:53 -0700
              Re: Q: Local variables initialization shortcut. Ike Naar <ike@sverige.freeshell.org> - 2012-06-02 17:08 +0000
              Re: Q: Local variables initialization shortcut. "io_x" <a@b.c.invalid> - 2012-06-03 10:33 +0200
                Re: Q: Local variables initialization shortcut. "io_x" <a@b.c.invalid> - 2012-06-03 11:32 +0200
        Re: Q: Local variables initialization shortcut. pete <pfiland@mindspring.com> - 2012-06-02 08:03 -0400
          Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 05:18 -0700
      Re: Q: Local variables initialization shortcut. "io_x" <a@b.c.invalid> - 2012-06-03 10:32 +0200
    Re: Q: Local variables initialization shortcut. "BartC" <bc@freeuk.com> - 2012-06-02 11:45 +0100
      Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 04:17 -0700
        Re: Q: Local variables initialization shortcut. "BartC" <bc@freeuk.com> - 2012-06-02 12:40 +0100
          Re: Q: Local variables initialization shortcut. "BartC" <bc@freeuk.com> - 2012-06-02 12:51 +0100
          Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 04:57 -0700
            Re: Q: Local variables initialization shortcut. "BartC" <bc@freeuk.com> - 2012-06-02 14:00 +0100
              Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 06:12 -0700
                Re: Q: Local variables initialization shortcut. Eric Sosman <esosman@ieee-dot-org.invalid> - 2012-06-02 09:58 -0400
                  Re: Q: Local variables initialization shortcut. David Brown <david.brown@hesbynett.no> - 2012-06-03 15:41 -0500
                Re: Q: Local variables initialization shortcut. Robert Wessel <robertwessel2@yahoo.com> - 2012-06-02 11:45 -0500
    Re: Q: Local variables initialization shortcut. Noob <root@localhost> - 2012-06-02 16:05 +0200
      Re: Q: Local variables initialization shortcut. Jean-Christophe <5.d@free.fr> - 2012-06-02 07:48 -0700
        Re: Q: Local variables initialization shortcut. "BartC" <bc@freeuk.com> - 2012-06-02 18:31 +0100
        Re: Q: Local variables initialization shortcut. jt@toerring.de (Jens Thoms Toerring) - 2012-06-02 17:50 +0000

Page 1 of 4  [1] 2 3 4  Next page →


#21648 — Q: Local variables initialization shortcut.

FromJean-Christophe <5.d@free.fr>
Date2012-06-02 02:49 -0700
SubjectQ: Local variables initialization shortcut.
Message-ID<5835baa1-db3f-4b81-a9e9-3ea20a632ba8@w24g2000vby.googlegroups.com>
Hi all,

The function f() has some local (double)
which should all be initialized to zero :

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

Can I use a shortcut like this :

 memset( &a, 0, number_of_variables * sizeof(double) );

If yes, can I do this :

 memset( &a, 0, (&z - &a + sizeof(double)) );

Like this :

void f(void)
{
double a,b,c,d,...,x,y,z;

 memset( &a, 0, (unsigned int)( &z - &a + sizeof(double) ) );

 ...
}

--------

PS :
Of course the # of variables is not always 26,
that's why I want an easy way to implement initialization to zero.

[toc] | [next] | [standalone]


#21649

FromChina Blue Max <chine.bleu@yahoo.com>
Date2012-06-02 03:03 -0700
Message-ID<chine.bleu-0321A0.03030502062012@news.eternal-september.org>
In reply to#21648
In article <5835baa1-db3f-4b81-a9e9-3ea20a632ba8@w24g2000vby.googlegroups.com>,
 Jean-Christophe <5.d@free.fr> wrote:

> Hi all,
> 
> The function f() has some local (double)
> which should all be initialized to zero :
> 
>  a = b = c =  ... = y = z = 0.0;
> 
> Can I use a shortcut like this :

No.

You cannot assume anything about assignment of variables to memory.

-- 
My name Indigo Montoya.      |                     The Dude abides.
You flamed my father.        |       I'm whoever you want me to be.
Prepare to be spanked.       |  Annoying Usenet one post at a time.
Stop posting that!           |    At least I can stay in character.

[toc] | [prev] | [next] | [standalone]


#21652

FromJean-Christophe <5.d@free.fr>
Date2012-06-02 03:17 -0700
Message-ID<abf174cc-00a7-47c3-bb43-75abc138c14c@6g2000vbv.googlegroups.com>
In reply to#21649
On 2 juin, 12:03, China Blue Max :

| Jean-Christophe :
| Can I use a shortcut like this (...)

> No.
> You cannot assume anything about assignment of variables to memory.

*sigh* ... okay, thanks !

[toc] | [prev] | [next] | [standalone]


#21650

Fromjacob navia <jacob@spamsink.net>
Date2012-06-02 12:06 +0200
Message-ID<jqcoij$ifu$1@speranza.aioe.org>
In reply to#21648
Le 02/06/12 11:49, Jean-Christophe a écrit :
> Hi all,
>
> The function f() has some local (double)
> which should all be initialized to zero :
>
>   a = b = c =  ... = y = z = 0.0;
>
> Can I use a shortcut like this :
>
>   memset(&a, 0, number_of_variables * sizeof(double) );
>
> If yes, can I do this :
>
>   memset(&a, 0, (&z -&a + sizeof(double)) );
>
> Like this :
>
> void f(void)
> {
> double a,b,c,d,...,x,y,z;
>
>   memset(&a, 0, (unsigned int)(&z -&a + sizeof(double) ) );
>
>   ...
> }
>
> --------
>
> PS :
> Of course the # of variables is not always 26,
> that's why I want an easy way to implement initialization to zero.
>

No, in general you can't. The compiler may align the double variables at 
a 16 byte boundary for instance, for performance reasons. That would 
mean that the compiler would leave 8 bytes unused between each variable.

Another problem could be that the compiler doesn't store those variables 
in a contiguos fashion but interleaves variables with other data (maybe 
because alignment reasons)

An easy solution to your problem is:

#include <stdio.h>
int main(void) {
     int i;

     for (i='a'; i<= 'z'; i++) {
           printf("\t%c = 0.0;\n",i);
     }
}

Redirect the output to a file and insert that file
into your source code

:-)

[toc] | [prev] | [next] | [standalone]


#21653

FromJean-Christophe <5.d@free.fr>
Date2012-06-02 03:25 -0700
Message-ID<f6919deb-bb2f-431b-93a2-0a2628708797@d17g2000vbv.googlegroups.com>
In reply to#21650
On 2 juin, 12:06, jacob navia :

| Can I use a shortcut like this (...)

> No, in general you can't. The compiler may align the double variables at
> a 16 byte boundary for instance, for performance reasons. That would
> mean that the compiler would leave 8 bytes unused between each variable.
> Another problem could be that the compiler doesn't store those variables
> in a contiguos fashion but interleaves variables with other data (maybe
> because alignment reasons)

Okay, thanks.

Since these variables are located in the stack,
is there a way to FORCE the compiler to align them,
using a compiler directive or something ?


> An easy solution to your problem is:
> #include <stdio.h>
> int main(void) {
>      int i;
>      for (i='a'; i<= 'z'; i++) {
>            printf("\t%c = 0.0;\n",i);
>      }
> }
> Redirect the output to a file and insert
> that file into your source code :-)

That's not what I call 'easy'.

[toc] | [prev] | [next] | [standalone]


#21689

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-06-02 10:59 -0400
Message-ID<jqd9oe$o5m$1@dont-email.me>
In reply to#21653
On 06/02/2012 06:25 AM, Jean-Christophe wrote:
> On 2 juin, 12:06, jacob navia :
> 
> | Can I use a shortcut like this (...)
> 
>> No, in general you can't. The compiler may align the double variables at
>> a 16 byte boundary for instance, for performance reasons. That would
>> mean that the compiler would leave 8 bytes unused between each variable.
>> Another problem could be that the compiler doesn't store those variables
>> in a contiguos fashion but interleaves variables with other data (maybe
>> because alignment reasons)
> 
> Okay, thanks.
> 
> Since these variables are located in the stack,
> is there a way to FORCE the compiler to align them,
> using a compiler directive or something ?

Yes - but it's not a compiler directive, it's "something" called an
array. Instead of a, b, c, ..., z, use arr[0], arr[1], arr[2], ...,
arr[25]. Then you could use memset() on the entire array.

Keep in mind that memset() set the specified number of bytes,
interpreted as unsigned char, to the specified value. If that value is
0, on many systems that will cause the doubles to have a value of 0.0.
In C99, if __STDC_IEC_559__ is pre-defined by the implementation, that's
guaranteed to be true. However, if using C90, or if __STDC_IEC_559__ is
not pre-defined, an implementation is allowed to use a floating point
representation were all-bits-0 represents some other number entirely, or
even a NaN. It could even be a trap representation, in which case any
attempt to retrieve the value of the double objects after calling
memset() has undefined behavior.

The easiest way to portably guarantee that your floating point values
are zero-initialized is to do so explicitly:

	double a=0, b=0, c=0, ..., z=0;

if you follow my suggestion, and use an array, you can save a lot of typing:

	double arr[26] = {0};

You should understand what that does: it explicitly sets arr[0] to 0,
and implicitly zero-initializes the other 25 elements to 0. There's a
common misunderstanding of code like this; the easiest way to correct
that misunderstanding it to consider the following alternative:

	double arr[26] = {1};

That does NOT set ever element of arr to 1. It explicitly sets arr[0] to
1, but the remaining 25 elements would still be implicitly zero-initialized.

>> An easy solution to your problem is:
>> #include <stdio.h>
>> int main(void) {
>>      int i;
>>      for (i='a'; i<= 'z'; i++) {
>>            printf("\t%c = 0.0;\n",i);
>>      }
>> }
>> Redirect the output to a file and insert
>> that file into your source code :-)
> 
> That's not what I call 'easy'.

The :-) was your clue that it was a joke.  He was basically hinting at
the 'a=0, b=0, c=0' approach I described above.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#21709

FromJean-Christophe <5.d@free.fr>
Date2012-06-02 13:02 -0700
Message-ID<28f08325-a2ff-4c39-b6a5-8abfaf9ad93a@d17g2000vbv.googlegroups.com>
In reply to#21689
On 2 juin, 16:59, James Kuyper <jameskuy...@verizon.net> wrote:

> > Since these variables are located in the stack,
> > is there a way to FORCE the compiler to align them,
> > using a compiler directive or something ?

> Yes - but it's not a compiler directive

So it's "No" since it's not a compiler directive.

[toc] | [prev] | [next] | [standalone]


#21722

FromKeith Thompson <kst-u@mib.org>
Date2012-06-02 14:51 -0700
Message-ID<lnvcj9fklo.fsf@nuthaus.mib.org>
In reply to#21709
Jean-Christophe <5.d@free.fr> writes:
> On 2 juin, 16:59, James Kuyper <jameskuy...@verizon.net> wrote:
>> > Since these variables are located in the stack,
>> > is there a way to FORCE the compiler to align them,
>> > using a compiler directive or something ?
>
>> Yes - but it's not a compiler directive
>
> So it's "No" since it's not a compiler directive.

It's "Yes" since it's an "or something".

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#21651

FromIan Collins <ian-news@hotmail.com>
Date2012-06-02 22:10 +1200
Message-ID<a2u74aF47aU1@mid.individual.net>
In reply to#21648
On 06/ 2/12 09:49 PM, Jean-Christophe wrote:
> Hi all,
>
> The function f() has some local (double)
> which should all be initialized to zero :
>
>   a = b = c =  ... = y = z = 0.0;
>
> Can I use a shortcut like this :
>
>   memset(&a, 0, number_of_variables * sizeof(double) );
>
> If yes, can I do this :
>
>   memset(&a, 0, (&z -&a + sizeof(double)) );
>
> Like this :
>
> void f(void)
> {
> double a,b,c,d,...,x,y,z;
>
>   memset(&a, 0, (unsigned int)(&z -&a + sizeof(double) ) );
>
>   ...
> }
>
> --------
>
> PS :
> Of course the # of variables is not always 26,
> that's why I want an easy way to implement initialization to zero.

If they need to be initialised, declare and initialise them when they 
are first used.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#21654

Fromjt@toerring.de (Jens Thoms Toerring)
Date2012-06-02 10:31 +0000
Message-ID<a2u8bhF5u8U1@mid.uni-berlin.de>
In reply to#21648
Jean-Christophe <5.d@free.fr> wrote:
> The function f() has some local (double)
> which should all be initialized to zero :

> double a,b,c,d,...,x,y,z;
> a = b = c =  ... = y = z = 0.0;

> Can I use a shortcut like this :

>  memset( &a, 0, number_of_variables * sizeof(double) );

Your idea has a number of problems: for once, while it is
not unlikely that they are all in consecutive memory lo-
cations, that's not guaranteed - the simplest practical
reason would be that the compiler finds that one or more
of the variables is not really needs to  be kept in memory
and can be optimized to reside in a CPU register only. Se-
cond, even if that wouldn't be an issue, there is no reason
at all that 'a' should be at the lowest address - quite
often the variable defined last is the one with the lowest
address - this is completely at the discretion of the com-
piler. Finally not on all systems a 0.0 value is represen-
ted by all bits set to zero.

> If yes, can I do this :

>  memset( &a, 0, (&z - &a + sizeof(double)) );

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

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 };

                           Regards, Jens
-- 
  \   Jens Thoms Toerring  ___      jt@toerring.de
   \__________________________      http://toerring.de

[toc] | [prev] | [next] | [standalone]


#21657

FromJean-Christophe <5.d@free.fr>
Date2012-06-02 03:59 -0700
Message-ID<4f89a691-f680-4dbc-bdbc-363450ccc001@b26g2000vbt.googlegroups.com>
In reply to#21654
On 2 juin, 12:31, j...@toerring.de :

> Your idea has a number of problems: for once, while it is
> not unlikely that they are all in consecutive memory lo-
> cations, that's not guaranteed - the simplest practical
> reason would be that the compiler finds that one or more
> of the variables is not really needs to  be kept in memory
> and can be optimized to reside in a CPU register only. Se-
> cond, even if that wouldn't be an issue, there is no reason
> at all that 'a' should be at the lowest address - quite
> often the variable defined last is the one with the lowest
> address - this is completely at the discretion of the com-
> piler.

Okay.


> 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 ?


> '&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.
Except for this actual example (when variables are stored
in stack w/ their adresses allocated by the compiler)
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 );


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


> 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 !

Thanks, Jens.

[toc] | [prev] | [next] | [standalone]


#21662

Fromjt@toerring.de (Jens Thoms Toerring)
Date2012-06-02 11:55 +0000
Message-ID<a2uda9F4vcU1@mid.uni-berlin.de>
In reply to#21657
Jean-Christophe <5.d@free.fr> wrote:
> On 2 juin, 12:31, j...@toerring.de :
> > 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  ___      jt@toerring.de
   \__________________________      http://toerring.de

[toc] | [prev] | [next] | [standalone]


#21665

Frompete <pfiland@mindspring.com>
Date2012-06-02 08:15 -0400
Message-ID<4FCA03D2.4AB8@mindspring.com>
In reply to#21662
Jens Thoms Toerring wrote:
> 
> Jean-Christophe <5.d@free.fr> wrote:
> > On 2 juin, 12:31, j...@toerring.de :
 
> > > '&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.

On the machine that I am using, 
the following program outputs a pair of 1's.

#include <stdio.h>

int 
main( void )
{
    {
        double a, b;
        printf( "%d\n", ( int ) ( &a - &b ) );
    }
    {
        double b, a;
        printf( "%d\n", ( int ) ( &a - &b ) );
    }
    return 0;
}

-- 
pete

[toc] | [prev] | [next] | [standalone]


#21667

FromJean-Christophe <5.d@free.fr>
Date2012-06-02 05:37 -0700
Message-ID<0ecf3c52-be95-4a37-a6f0-42469d378f1e@m3g2000vbl.googlegroups.com>
In reply to#21662
On 2 juin, 13:55, j...@toerring.de (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.

[toc] | [prev] | [next] | [standalone]


#21675

Fromjt@toerring.de (Jens Thoms Toerring)
Date2012-06-02 13:35 +0000
Message-ID<a2uj5rFvv1U1@mid.uni-berlin.de>
In reply to#21667
Jean-Christophe <5.d@free.fr> wrote:
> On 2 juin, 13:55, j...@toerring.de (Jens Thoms Toerring) wrote:
> 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.

I don't agree - you are subtracting adresses and, as
long as you don't cross the border of undefined beha-
viour, it doesn't matter if you directly subtract the
addresses of two variables or first store those addres-
ses in pointers and then subtract their values. All what
(at least when used as defined by the standard, i.e.
when subtracting the addresses of elements of an array)
is the type of the elements. Thus

double a[ 10 ];
double  * ap2 = &a[ 2 ],
        * ap7 = &a[ 7 ];
printf( "%d %d\n", ( int ) ( &a[ 7 ] - &a[ 2 ] ),
                   ( int ) ( ap7 - ap2 ) );

will always output "5 5", the number of elements in
between (and you're guaranteed that later elements in
the array have higher addresses). If you want the
number of bytes then you have to either multiply by
the size of a double or cast the addresses of the
array elements to char before subtracting them.

When instead of doing that on elements of an array
on addresses of unrelated objects then the results
could actually be different, but there's nothing which
would tell you which one is correct or to be expected -
the compiler writer can pick whatever behaviour (s)he
considers appropriate. It would also be "correct" when
the result would always be 42.

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

You may indeed have gotten used to a "dialect" of C (or
certain ways those compilers handle things not defined
by the standard) and you may have to unlearn a few things
you are taking for granted. Bin there, done that and
sweared quite a bit along the way;-) And it's sometimes
quite hard to grasp why certain constructs aren't well
defined by the standard, especially when one comes from
an assembler background and for quite a number of things
there is an "obvious" way in which one would assumes they
should be dealt with. There's a long list of things that
are either unspecified, undefined or implementation defined
at the end of the C99 standard (Annex J). It's not an easy
read but can help a bit getting an idea what one should
avoid when trying to write portable programs.

                             Regards, Jens
-- 
  \   Jens Thoms Toerring  ___      jt@toerring.de
   \__________________________      http://toerring.de

[toc] | [prev] | [next] | [standalone]


#21676

FromJean-Christophe <5.d@free.fr>
Date2012-06-02 06:47 -0700
Message-ID<0e159ddf-1c62-4bc2-bb70-a8369dec0c00@a16g2000vby.googlegroups.com>
In reply to#21675
On 2 juin, 15:35, j...@toerring.de (Jens Thoms Toerring) wrote:

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

> I don't agree (...)

Yes, sorry about that.
What I had in mind was this :

#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;
}

Output :
 ib - ia = 8 // = sizeof(double)
 ia - ib = 4294967288 // 0xFFFFFFF8


> When instead of doing that on elements of an array
> on addresses of unrelated objects then the results
> could actually be different, but there's nothing which
> would tell you which one is correct or to be expected -
> the compiler writer can pick whatever behaviour (s)he
> considers appropriate. It would also be "correct" when
> the result would always be 42.

I got that !
(Douglas Noel Adams, uh ?)


> You may indeed have gotten used to a "dialect" of C (or
> certain ways those compilers handle things not defined
> by the standard) and you may have to unlearn a few things
> you are taking for granted. Bin there, done that and
> sweared quite a bit along the way;-) And it's sometimes
> quite hard to grasp why certain constructs aren't well
> defined by the standard, especially when one comes from
> an assembler background

That's it : I'm an electronician.


> and for quite a number of things
> there is an "obvious" way in which one would assumes they
> should be dealt with. There's a long list of things that
> are either unspecified, undefined or implementation defined
> at the end of the C99 standard (Annex J). It's not an easy
> read but can help a bit getting an idea what one should
> avoid when trying to write portable programs.

Thanks again, Jens.

[toc] | [prev] | [next] | [standalone]


#21684

From"BartC" <bc@freeuk.com>
Date2012-06-02 15:08 +0100
Message-ID<jqd6od$6s7$1@dont-email.me>
In reply to#21676

"Jean-Christophe" <5.d@free.fr> wrote in message
news:0e159ddf-1c62-4bc2-bb70-a8369dec0c00@a16g2000vby.googlegroups.com...
> On 2 juin, 15:35, j...@toerring.de (Jens Thoms Toerring) wrote:
>
>> >  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.
>
>> I don't agree (...)
>
> Yes, sorry about that.
> What I had in mind was this :
>
>#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;
>}


(char* can be used in place of unsigned int here.)

> Output :
> ib - ia = 8 // = sizeof(double)
> ia - ib = 4294967288 // 0xFFFFFFF8

The trouble is code like this:

double a;
char x;
double b;

On a machine which doesn't need to align doubles, it's quite possible that
(char*)&a - (char*)&b might be 9 bytes. (I don't know what C would do with
&a-&b in that case; possibly divide the 9 bytes by 8 to get 1, the answer
you expect.)

You might try this:

#include <stdio.h>
double a;
char x,y,z;
double b;

int main(void)
{
 printf( "&a = %u\n", (unsigned int)&a);
 printf( "&b = %u\n", (unsigned int)&b);
 printf( "&x = %u\n", (unsigned int)&x);
 printf( "&y = %u\n", (unsigned int)&y);
 printf( "&z = %u\n", (unsigned int)&z);
 return 0;
}

You'll probably find the addresses are all mixed up.

Even when *all* variables are doubles, you won't know which have the lowest
and highest addresses.

-- 
Bartc  

[toc] | [prev] | [next] | [standalone]


#21687

FromJean-Christophe <5.d@free.fr>
Date2012-06-02 07:37 -0700
Message-ID<7ff937d6-bd95-4235-9378-06f92d6f6d40@fr28g2000vbb.googlegroups.com>
In reply to#21684
On Jun 2, 4:08 pm, "BartC" :

> #include <stdio.h>
> double a;
> char x,y,z;
> double b;
> int main(void)
> { printf( "&a = %u\n", (unsigned int)&a);
>   printf( "&b = %u\n", (unsigned int)&b);
>   printf( "&x = %u\n", (unsigned int)&x);
>   printf( "&y = %u\n", (unsigned int)&y);
>   printf( "&z = %u\n", (unsigned int)&z);
>   return 0;
> }

Output :

&a = 4221624
&b = 4221632
&x = 4221640
&y = 4221641
&z = 4221642

> You'll probably find the addresses are all mixed up.
> Even when *all* variables are doubles, you won't know
> which have the lowest and highest addresses.

:o)

[toc] | [prev] | [next] | [standalone]


#21690

From"BartC" <bc@freeuk.com>
Date2012-06-02 16:17 +0100
Message-ID<jqdaq0$v02$1@dont-email.me>
In reply to#21687
"Jean-Christophe" <5.d@free.fr> wrote in message
news:7ff937d6-bd95-4235-9378-06f92d6f6d40@fr28g2000vbb.googlegroups.com...
> On Jun 2, 4:08 pm, "BartC" :

> Output :
>
> &a = 4221624
> &b = 4221632
> &x = 4221640
> &y = 4221641
> &z = 4221642

I tried it on four x86-32 compilers, and get the following (I've added an
extra term to highlight the differences):

&a = 4202528 0
&b = 4202544 16
&x = 4202552 -4
&y = 4202540 -12
&z = 4202536 -4

&a = 4214968 0
&b = 4214984 16
&x = 4214992 -7
&y = 4214977 -15
&z = 4214976 -1

&a = 4244000 0
&b = 4244008 8
&x = 4245044 1037
&y = 4245045 1
&z = 4245046 1

&a = 4231444 0
&b = 4231452 8
&x = 4231464 8
&y = 4231460 -4
&z = 4231468 8

The following was from a non-C compiler (although it's possible that some C
compiler could return this too):

&a = 1638040 0
&b = 1638028 -12
&x = 1638039 11
&y = 1638038 -1
&z = 1638037 -1

>> You'll probably find the addresses are all mixed up.
>> Even when *all* variables are doubles, you won't know
>> which have the lowest and highest addresses.
>
> :o)

While in the C examples, 'a' had the lower address, I don't see how this can
guaranteed (and you might expect it to have higher address, if allocated
first and the stack frame growing downwards). And in general you can't know
what order variables might be allocated in (perhaps in declaration order,
perhaps in alphabetical order, but it can be anything). Or some might not 
exist in memory at all.

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#21702

From"BartC" <bc@freeuk.com>
Date2012-06-02 19:02 +0100
Message-ID<jqdkga$qnb$1@dont-email.me>
In reply to#21690

"BartC" <bc@freeuk.com> wrote in message news:jqdaq0$v02$1@dont-email.me...
> "Jean-Christophe" <5.d@free.fr> wrote in message
> news:7ff937d6-bd95-4235-9378-06f92d6f6d40@fr28g2000vbb.googlegroups.com...
>> On Jun 2, 4:08 pm, "BartC" :
>
>> Output :
>>
>> &a = 4221624
>> &b = 4221632

> I tried it on four x86-32 compilers, and get the following (I've added an
> extra term to highlight the differences):

<Snip differences of +16, +16, +8, +8 between &a and &b (static)>

>>> You'll probably find the addresses are all mixed up.
>>> Even when *all* variables are doubles, you won't know
>>> which have the lowest and highest addresses.

> While in the C examples, 'a' had the lower address, I don't see how this
> can
> guaranteed (and you might expect it to have higher address, if allocated
> first and the stack frame growing downwards).

Jens' reply reminds me that, for some reason, your test was on static
variables. Rerunning the test on local variables, then generally a had the 
higher address.

That's with just two doubles. Declaring doubles a,b,c,d,e (with other 
variables interspersed), and displaying the difference between &d and &b, I 
was getting results of +8, -16 and +16 over four compilers.

-- 
Bartc

 

[toc] | [prev] | [next] | [standalone]


Page 1 of 4  [1] 2 3 4  Next page →

Back to top | Article view | comp.lang.c


csiph-web