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


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

setting pointers to NULL and testing question.

Started byG G <gdotone@gmail.com>
First post2016-06-12 16:21 -0700
Last post2016-06-16 21:39 -0700
Articles 20 on this page of 86 — 20 participants

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


Contents

  setting pointers to NULL and testing question. G G <gdotone@gmail.com> - 2016-06-12 16:21 -0700
    Re: setting pointers to NULL and testing question. Richard Heathfield <rjh@cpax.org.uk> - 2016-06-13 00:50 +0100
      Re: setting pointers to NULL and testing question. G G <gdotone@gmail.com> - 2016-06-12 17:03 -0700
      Re: setting pointers to NULL and testing question. Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2016-06-12 20:25 -0600
        Re: setting pointers to NULL and testing question. James Kuyper <jameskuyper@verizon.net> - 2016-06-12 22:57 -0400
          Re: setting pointers to NULL and testing question. Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2016-06-13 10:03 -0600
            Re: setting pointers to NULL and testing question. Tim Rentsch <txr@alumni.caltech.edu> - 2016-06-15 14:43 -0700
        Re: setting pointers to NULL and testing question. supercat@casperkitty.com - 2016-06-13 08:06 -0700
          Re: setting pointers to NULL and testing question. Richard Damon <Richard@Damon-Family.org> - 2016-06-16 08:27 -0400
            Re: setting pointers to NULL and testing question. supercat@casperkitty.com - 2016-06-16 06:27 -0700
              Re: setting pointers to NULL and testing question. supercat@casperkitty.com - 2016-06-16 07:31 -0700
              Re: setting pointers to NULL and testing question. Richard Damon <Richard@Damon-Family.org> - 2016-06-18 13:39 -0400
                Re: setting pointers to NULL and testing question. supercat@casperkitty.com - 2016-06-18 11:37 -0700
                  Re: setting pointers to NULL and testing question. Richard Damon <Richard@Damon-Family.org> - 2016-06-18 17:17 -0400
                    Re: setting pointers to NULL and testing question. supercat@casperkitty.com - 2016-06-18 17:22 -0700
        Re: setting pointers to NULL and testing question. James Kuyper <jameskuyper@verizon.net> - 2016-06-13 14:10 -0400
          Re: setting pointers to NULL and testing question. Keith Thompson <kst-u@mib.org> - 2016-06-13 11:28 -0700
          Re: setting pointers to NULL and testing question. Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2016-06-13 12:31 -0600
      Re: setting pointers to NULL and testing question. Keith Thompson <kst-u@mib.org> - 2016-06-12 19:38 -0700
        Re: setting pointers to NULL and testing question. Richard Heathfield <rjh@cpax.org.uk> - 2016-06-13 07:35 +0100
      Re: setting pointers to NULL and testing question. Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-06-13 11:40 +0100
        Re: setting pointers to NULL and testing question. BartC <bc@freeuk.com> - 2016-06-13 11:56 +0100
          Re: setting pointers to NULL and testing question. Martin Shobe <mashobe9@gmail.com> - 2016-06-13 06:22 -0500
            Re: setting pointers to NULL and testing question. BartC <bc@freeuk.com> - 2016-06-13 12:39 +0100
              Re: setting pointers to NULL and testing question. Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-06-13 15:22 +0100
                Re: setting pointers to NULL and testing question. BartC <bc@freeuk.com> - 2016-06-13 17:34 +0100
                  Re: setting pointers to NULL and testing question. Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-06-13 19:31 +0100
                    Re: setting pointers to NULL and testing question. BartC <bc@freeuk.com> - 2016-06-13 20:17 +0100
                      Re: setting pointers to NULL and testing question. Keith Thompson <kst-u@mib.org> - 2016-06-13 12:47 -0700
                        Re: setting pointers to NULL and testing question. Tim Rentsch <txr@alumni.caltech.edu> - 2016-06-15 16:44 -0700
                          Re: setting pointers to NULL and testing question. Keith Thompson <kst-u@mib.org> - 2016-06-15 17:20 -0700
        Re: setting pointers to NULL and testing question. Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-06-13 04:01 -0700
          Re: setting pointers to NULL and testing question. Tim Rentsch <txr@alumni.caltech.edu> - 2016-06-16 12:57 -0700
        Re: setting pointers to NULL and testing question. Richard Heathfield <rjh@cpax.org.uk> - 2016-06-13 12:18 +0100
          Re: setting pointers to NULL and testing question. David Brown <david.brown@hesbynett.no> - 2016-06-13 14:01 +0200
            Re: setting pointers to NULL and testing question. Richard Heathfield <rjh@cpax.org.uk> - 2016-06-13 14:15 +0100
              Re: setting pointers to NULL and testing question. David Brown <david.brown@hesbynett.no> - 2016-06-13 15:37 +0200
                Re: setting pointers to NULL and testing question. Richard Heathfield <rjh@cpax.org.uk> - 2016-06-13 14:48 +0100
          Re: setting pointers to NULL and testing question. Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-06-13 15:43 +0100
    Re: setting pointers to NULL and testing question. Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-06-12 17:54 -0700
    Re: setting pointers to NULL and testing question. John Bode <jfbode1029@gmail.com> - 2016-06-14 08:36 -0700
      Re: setting pointers to NULL and testing question. Richard Heathfield <rjh@cpax.org.uk> - 2016-06-14 16:41 +0100
      Re: setting pointers to NULL and testing question. Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-06-14 09:01 -0700
      Re: setting pointers to NULL and testing question. "James R. Kuyper" <jameskuyper@verizon.net> - 2016-06-14 13:25 -0400
        Re: setting pointers to NULL and testing question. supercat@casperkitty.com - 2016-06-14 10:48 -0700
          Re: setting pointers to NULL and testing question. Ian Collins <ian-news@hotmail.com> - 2016-06-15 08:24 +1200
            Re: setting pointers to NULL and testing question. "James R. Kuyper" <jameskuyper@verizon.net> - 2016-06-14 16:57 -0400
              Re: setting pointers to NULL and testing question. supercat@casperkitty.com - 2016-06-14 14:29 -0700
                Re: setting pointers to NULL and testing question. BartC <bc@freeuk.com> - 2016-06-14 22:41 +0100
                  Re: setting pointers to NULL and testing question. supercat@casperkitty.com - 2016-06-14 15:16 -0700
                    Re: setting pointers to NULL and testing question. Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-06-15 00:25 +0100
                      Re: setting pointers to NULL and testing question. Keith Thompson <kst-u@mib.org> - 2016-06-14 16:58 -0700
                      Re: setting pointers to NULL and testing question. David Brown <david.brown@hesbynett.no> - 2016-06-15 09:28 +0200
                        Re: setting pointers to NULL and testing question. Keith Thompson <kst-u@mib.org> - 2016-06-15 09:57 -0700
                Re: setting pointers to NULL and testing question. David Brown <david.brown@hesbynett.no> - 2016-06-15 09:23 +0200
                  Re: setting pointers to NULL and testing question. Richard Heathfield <rjh@cpax.org.uk> - 2016-06-15 08:35 +0100
                    Re: setting pointers to NULL and testing question. Richard Heathfield <rjh@cpax.org.uk> - 2016-06-15 08:37 +0100
                    Re: setting pointers to NULL and testing question. David Brown <david.brown@hesbynett.no> - 2016-06-15 10:42 +0200
                      Re: setting pointers to NULL and testing question. Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-06-15 13:28 +0100
                  Re: setting pointers to NULL and testing question. supercat@casperkitty.com - 2016-06-15 11:41 -0700
                  Re: setting pointers to NULL and testing question. raltbos@xs4all.nl (Richard Bos) - 2016-06-15 19:43 +0000
                    Re: setting pointers to NULL and testing question. supercat@casperkitty.com - 2016-06-15 13:09 -0700
                    Re: setting pointers to NULL and testing question. David Brown <david.brown@hesbynett.no> - 2016-06-15 22:31 +0200
                    Re: setting pointers to NULL and testing question. Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-15 17:11 -0400
                      Re: setting pointers to NULL and testing question. raltbos@xs4all.nl (Richard Bos) - 2016-06-18 20:44 +0000
                        Re: setting pointers to NULL and testing question. Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-18 17:20 -0400
          Re: setting pointers to NULL and testing question. Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-06-14 23:22 -0700
            Re: setting pointers to NULL and testing question. Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-06-15 13:23 +0100
        Re: setting pointers to NULL and testing question. John Bode <jfbode1029@gmail.com> - 2016-06-20 13:36 -0700
      Re: setting pointers to NULL and testing question. Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-14 14:59 -0400
        Re: setting pointers to NULL and testing question. "James R. Kuyper" <jameskuyper@verizon.net> - 2016-06-14 15:17 -0400
        Re: setting pointers to NULL and testing question. Richard Heathfield <rjh@cpax.org.uk> - 2016-06-14 20:25 +0100
        Re: setting pointers to NULL and testing question. Tim Rentsch <txr@alumni.caltech.edu> - 2016-06-15 19:48 -0700
          Re: setting pointers to NULL and testing question. Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-15 23:25 -0400
            Re: setting pointers to NULL and testing question. James Kuyper <jameskuyper@verizon.net> - 2016-06-16 12:11 -0400
              Re: setting pointers to NULL and testing question. supercat@casperkitty.com - 2016-06-16 09:25 -0700
              Re: setting pointers to NULL and testing question. Tim Rentsch <txr@alumni.caltech.edu> - 2016-06-16 21:46 -0700
                Re: setting pointers to NULL and testing question. Gareth Owen <gwowen@gmail.com> - 2016-06-17 06:13 +0100
                  Re: setting pointers to NULL and testing question. Robert Wessel <robertwessel2@yahoo.com> - 2016-06-17 02:03 -0500
                    Re: setting pointers to NULL and testing question. Martin Shobe <mashobe9@gmail.com> - 2016-06-17 07:07 -0500
                  Re: setting pointers to NULL and testing question. supercat@casperkitty.com - 2016-06-17 03:18 -0700
                  Re: setting pointers to NULL and testing question. James Kuyper <jameskuyper@verizon.net> - 2016-06-17 09:16 -0400
                    Re: setting pointers to NULL and testing question. Tim Rentsch <txr@alumni.caltech.edu> - 2016-06-21 11:03 -0700
                  Re: setting pointers to NULL and testing question. Tim Rentsch <txr@alumni.caltech.edu> - 2016-06-21 10:58 -0700
                Re: setting pointers to NULL and testing question. Keith Thompson <kst-u@mib.org> - 2016-06-21 11:28 -0700
            Re: setting pointers to NULL and testing question. Tim Rentsch <txr@alumni.caltech.edu> - 2016-06-16 21:39 -0700

Page 3 of 5 — ← Prev page 1 2 [3] 4 5  Next page →


#89075

FromJohn Bode <jfbode1029@gmail.com>
Date2016-06-14 08:36 -0700
Message-ID<a96444e4-ffcd-458e-bffb-6e95ed5d812b@googlegroups.com>
In reply to#88991
On Sunday, June 12, 2016 at 6:21:40 PM UTC-5, G G wrote:
> when should a pointer to set to NULL and test whether
> it is NULL?

In a non-static declaration, a pointer variable should always be initialized
explicitly to NULL or to a valid pointer value:

    T *p1 = NULL;
    T *p2 = &some_other_T_object;
    T *p3 = malloc( sizeof *p3 * number_of_elements );
    const char *prompt = "This is a prompt";

If no explicit initializer is present, the initial value of the variable
will be *indeterminate* (a random bit string that most likely won't 
correspond to NULL *or* a valid memory address) *unless* the variable is
declared at file scope (outside the body of any function) or with the
"static" keyword; in that case, the initial value will be NULL.    

A pointer variable should be set to NULL as soon as the thing it pointed to
ceases to exist or is no longer being used (e.g., you call free() on a
pointer value obtained from malloc()):

    T *ptr = malloc( sizeof *ptr * number_of_elements );
    /**
     * do stuff with ptr
     */
    free( ptr ); // deallocates storage obtained through malloc
    ptr = NULL;

You should test against NULL before dereferencing a pointer when 

    * obtaining a pointer value from any library function that can
      potentially return NULL, including but not limited to malloc(),
      realloc(), strtok(), strchr(), fopen(), etc.:

      FILE *fp = fopen( "some_file", "r" );
      if ( !fp ) // or fp == NULL
      {
        fprintf( stderr, "Could not open some_file, exiting...\n" );
        exit( EXIT_FAILURE );
      }

    * receiving a pointer value as a function argument without any
      guarantee that it's valid:

      void foo( void *data )
      {
        if ( !data )
        {
          // NULL input argument
          return;
        }

        // proceed as normal
      }

If you *know* that the pointer was initialized to the address of another
object, then you don't need to test against NULL before dereferencing ptr:

    char buf[N+1];
    ...
    for ( char *ptr = buf; *ptr != 0; ptr++ )
      // do something with *ptr  

Note that standard library functions like strcpy() and strcmp() *don't* 
perform NULL checks against their input arguments; they assume you've
done that work already.  

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


#89077

FromRichard Heathfield <rjh@cpax.org.uk>
Date2016-06-14 16:41 +0100
Message-ID<njp8je$p2t$1@dont-email.me>
In reply to#89075
On 14/06/16 16:36, John Bode wrote:
<snip>
>
> Note that standard library functions like strcpy() and strcmp() *don't*

s/don't/are not guaranteed or required to/

> perform NULL checks against their input arguments; they assume you've
> done that work already.

Library functions are certainly /allowed/ to perform that check if they 
want (because of the "as-if" rule). For those whose specification 
demands a non-null pointer, the behaviour is undefined when a null 
pointer is passed, so they're allowed to do something useful (like 
return a null pointer) if they so choose, or they might prefer to do 
something creative (like start playing an MP3).

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

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


#89079

FromMalcolm McLean <malcolm.mclean5@btinternet.com>
Date2016-06-14 09:01 -0700
Message-ID<19b881bf-264f-4233-8f1c-1925538f71f1@googlegroups.com>
In reply to#89075
On Tuesday, June 14, 2016 at 4:36:36 PM UTC+1, John Bode wrote:
> 
> Note that standard library functions like strcpy() and strcmp() *don't* 
> perform NULL checks against their input arguments; they assume you've
> done that work already.
>
Normally the library knows whether the system will trap a null dereference with
an error message, or blindly try to write over memory location 0.
If the former, there's not much point doing the check, just let the existing
protection handle it. If the latter, the normal approach would be to exit
gracefully with an error message rather then crash the system, unless
resources were extremely constrained.

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


#89081

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2016-06-14 13:25 -0400
Message-ID<4fb4f72a-1068-1d0e-37de-f10e29488332@verizon.net>
In reply to#89075
On 06/14/2016 11:36 AM, John Bode wrote:
> On Sunday, June 12, 2016 at 6:21:40 PM UTC-5, G G wrote:
>> when should a pointer to set to NULL and test whether
>> it is NULL?
> 
> In a non-static declaration, a pointer variable should always be initialized
> explicitly to NULL or to a valid pointer value:
> 
>     T *p1 = NULL;
>     T *p2 = &some_other_T_object;
>     T *p3 = malloc( sizeof *p3 * number_of_elements );
>     const char *prompt = "This is a prompt";
> 
> If no explicit initializer is present, the initial value of the variable
> will be *indeterminate* (a random bit string that most likely won't 
> correspond to NULL *or* a valid memory address) *unless* the variable is
> declared at file scope (outside the body of any function) or with the
> "static" keyword; in that case, the initial value will be NULL.

One caveat: Consider code such as the following:

T *p4 = NULL;

while(some_condition)
{
      // Many lines of code

      p4[n] = expression;

      // many more lines of code

      free(p4);
      p4 = malloc(desired_count * sizeof *p4);
      if(p4 == NULL)
      {
           // error handling
      }

      // even more lines of code
}

When preceded by appropriate startup code, and followed by appropriate
follow-up code, it can be a perfectly reasonable to write a loop like
this. However, it has not been preceded by the right startup code. If p4
had not been initialized, many compilers will warn you about the fact
that your code attempts to use an uninitialized value. With the NULL
initialization, you have disabled that warning.

My own personal criterion is to declare every variable with the smallest
scope that allows it to do the job that it needs to do. Then, if it can
be initialized at the point of declaration with a value that I intend to
use, I will do so. Otherwise, I will deliberately leave it uninitialized
until I can assign it such a value, thereby enabling the compiler
warning if I forget to create such an assignment.


> A pointer variable should be set to NULL as soon as the thing it pointed to
> ceases to exist or is no longer being used (e.g., you call free() on a
> pointer value obtained from malloc()):
> 
>     T *ptr = malloc( sizeof *ptr * number_of_elements );
>     /**
>      * do stuff with ptr
>      */
>     free( ptr ); // deallocates storage obtained through malloc
>     ptr = NULL;

I also disagree with this advice in some circumstances:

      if(condition)
      {
           T *ptr = malloc( sizeof *ptr * number_of_elements );
           if(ptr)
           {
               /* do stuff with ptr */
               free( ptr );
               ptr = NULL;
           }
      }

Because the scope of ptr is ending, there's no need to set it to NULL.
Granted, any decent compiler will optimize away ptr = NULL - but for
precisely that reason, many of the better compilers will warn you
"statement has no effect". I save my time, and the compiler's, by not
bothering to write such assignments in the first place.

> You should test against NULL before dereferencing a pointer when 
> 
>     * obtaining a pointer value from any library function that can
>       potentially return NULL, including but not limited to malloc(),
>       realloc(), strtok(), strchr(), fopen(), etc.:
> 
>       FILE *fp = fopen( "some_file", "r" );
>       if ( !fp ) // or fp == NULL
>       {
>         fprintf( stderr, "Could not open some_file, exiting...\n" );
>         exit( EXIT_FAILURE );
>       }
> 
>     * receiving a pointer value as a function argument without any
>       guarantee that it's valid:
> 
>       void foo( void *data )
>       {
>         if ( !data )
>         {
>           // NULL input argument
>           return;
>         }
> 
>         // proceed as normal
>       }

I agree with this advice completely. I personally only trust pointers
passed to my functions if they were passed there by other functions in
the same translation unit, or were returned by standard library
functions that were called with arguments that guarantee a non-NULL
value. All other pointers are checked against NULL.

Since I have to check pointer arguments for null values anyway, I try to
design my functions so that a null value has some well-defined meaning,
rather than being an error condition. Usually, that well-defined meaning
is to turn off that portion of the function's behavior that would
otherwise be associated with whatever that pointer is supposed to point
at. Obviously, this is not appropriate for arguments that are involved
in every aspect of the function's behavior.

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


#89082

Fromsupercat@casperkitty.com
Date2016-06-14 10:48 -0700
Message-ID<6f74737b-1cfd-4105-b6ca-2ad030a1c061@googlegroups.com>
In reply to#89081
On Tuesday, June 14, 2016 at 12:26:07 PM UTC-5, James R. Kuyper wrote:
> My own personal criterion is to declare every variable with the smallest
> scope that allows it to do the job that it needs to do. Then, if it can
> be initialized at the point of declaration with a value that I intend to
> use, I will do so. Otherwise, I will deliberately leave it uninitialized
> until I can assign it such a value, thereby enabling the compiler
> warning if I forget to create such an assignment.

It's too bad that most languages require all scopes to be strictly nested,
since there are many situations where the useful lifetime of some variables
will end precisely at the point when their value is used in computing the
initial/only value of another variable which will never be modified during
its lifetime.

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


#89091

FromIan Collins <ian-news@hotmail.com>
Date2016-06-15 08:24 +1200
Message-ID<dsb7ghFocnaU1@mid.individual.net>
In reply to#89082
On 06/15/16 05:48 AM, supercat@casperkitty.com wrote:
> On Tuesday, June 14, 2016 at 12:26:07 PM UTC-5, James R. Kuyper wrote:
>> My own personal criterion is to declare every variable with the smallest
>> scope that allows it to do the job that it needs to do. Then, if it can
>> be initialized at the point of declaration with a value that I intend to
>> use, I will do so. Otherwise, I will deliberately leave it uninitialized
>> until I can assign it such a value, thereby enabling the compiler
>> warning if I forget to create such an assignment.
>
> It's too bad that most languages require all scopes to be strictly nested,
> since there are many situations where the useful lifetime of some variables
> will end precisely at the point when their value is used in computing the
> initial/only value of another variable which will never be modified during
> its lifetime.

Try C++.... There temporary variable life time rules are pretty much as 
you describe.

-- 
Ian

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


#89093

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2016-06-14 16:57 -0400
Message-ID<7861f1fe-7e13-2e0b-5a0d-6de024da95c2@verizon.net>
In reply to#89091
On 06/14/2016 04:24 PM, Ian Collins wrote:
> On 06/15/16 05:48 AM, supercat@casperkitty.com wrote:
...
>> It's too bad that most languages require all scopes to be strictly nested,
>> since there are many situations where the useful lifetime of some variables
>> will end precisely at the point when their value is used in computing the
>> initial/only value of another variable which will never be modified during
>> its lifetime.
> 
> Try C++.... There temporary variable life time rules are pretty much as 
> you describe.

The as-if rule means, among other things, that an implementation is free
to reuse the memory allocated for a non-volatile object as soon as the
last expression reading the value stored in that object has been
executed. For a volatile object, it will have to wait until the last
expression writing to that object has also been executed. If aliasing
with defined behavior is a possibility, it will have to be taken into
consideration when determining which expression is the "last one" to
read or write from that object.

The fact that the lifetime might not terminate until quite a bit later
is irrelevant - under those circumstances, the observable behavior of
the program cannot depend upon whether or not that memory has been
reassigned to be used for some other purpose.

You can reasonably expect any decent compiler to perform such
optimizations, when justified. Whenever the order of evaluation of C
expressions is unspecified, or when allowed by the as-if rule, you can
reasonably expect decent compilers to sometimes figure out that
re-ordering some expression could create opportunities to perform this
optimization that would not exist if the code were translated naively.

So there isn't really much of a reason for saying "It's too bad ...".
For practical purposes, an implementation is allowed to generate code
that treats the object lifetime as if it ended precisely when supercat
wants it to end.

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


#89099

Fromsupercat@casperkitty.com
Date2016-06-14 14:29 -0700
Message-ID<22eb816c-faf2-403f-8438-f829caa9e252@googlegroups.com>
In reply to#89093
On Tuesday, June 14, 2016 at 3:58:00 PM UTC-5, James R. Kuyper wrote:
> So there isn't really much of a reason for saying "It's too bad ...".
> For practical purposes, an implementation is allowed to generate code
> that treats the object lifetime as if it ended precisely when supercat
> wants it to end.

My point was not about code generation, but rather to respond to the
comment about the desirability of scoping variables as narrowly as
possible.  Perhaps I should have used some word other than "temporary",
which has technical meaning, when what I meant to say was a variable which
is used briefly for some purpose but never again.  If I
want to do something like:

    double dx = monster.x-player.x;
    double dy = monster.y-player.y
    double monster_distance = sqrt(dx*dx+dy*dy);

and never need dx and dy after that, then their scope should ideally start
at the point of their declaration and end with the declaration of distance,
whereupon the *identifiers* could be freed up for other purposes.  While
one could use:

    double dx,dy
    ...    
    dx = monster.x-player.x;
    dy = monster.y-player.y
    double monster_distance = sqrt(dx*dx+dy*dy);
    ...
    dx = shot.x-player.x;
    dy = shot.y-player.y
    double shot_distance = sqrt(dx*dx+dy*dy);

or

    double monster_distance;
    {
      double dx = monster.x-player.x;
      double dy = monster.y-player.y
      monster_distance = sqrt(dx*dx+dy*dy);
    }
    double shot_distance;
    {
      double dx = shot.x-player.x;
      double dy = shot.y-player.y
      shot_distance = sqrt(dx*dx+dy*dy);
    }

or

    double dx1 = monster.x-player.x;
    double dy1 = monster.y-player.y
    double monster_distance = sqrt(dx1*dx1+dy1*dy1);
    ...
    double dx2 = shot.x-player.x;
    double dy2 = shot.y-player.y
    double shot_distance = sqrt(dx2*dx2+dy2*dy2);

the first approach vastly over-extends the scope of dx and dy, the
second creates monster_distance and shot_distance without any kind of
meaningful initial value, and the third approach clutters up the scope
with excessive variable names.

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


#89103

FromBartC <bc@freeuk.com>
Date2016-06-14 22:41 +0100
Message-ID<njptmj$bit$1@dont-email.me>
In reply to#89099
On 14/06/2016 22:29, supercat@casperkitty.com wrote:
> On Tuesday, June 14, 2016 at 3:58:00 PM UTC-5, James R. Kuyper wrote:
>> So there isn't really much of a reason for saying "It's too bad ...".
>> For practical purposes, an implementation is allowed to generate code
>> that treats the object lifetime as if it ended precisely when supercat
>> wants it to end.
>
> My point was not about code generation, but rather to respond to the
> comment about the desirability of scoping variables as narrowly as
> possible.  Perhaps I should have used some word other than "temporary",
> which has technical meaning, when what I meant to say was a variable which
> is used briefly for some purpose but never again.  If I
> want to do something like:
>
>     double dx = monster.x-player.x;
>     double dy = monster.y-player.y
>     double monster_distance = sqrt(dx*dx+dy*dy);
>
> and never need dx and dy after that, then their scope should ideally start
> at the point of their declaration and end with the declaration of distance,
> whereupon the *identifiers* could be freed up for other purposes.  While
> one could use:

With gcc you can try this:

      double monster_distance = ({
          double dx = monster.x-player.x;
          double dy = monster.y-player.y;
          sqrt(dx*dx+dy*dy);});


-- 
Bartc

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


#89110

Fromsupercat@casperkitty.com
Date2016-06-14 15:16 -0700
Message-ID<8d1f537d-fec5-490f-8804-aefed8cb2d56@googlegroups.com>
In reply to#89103
On Tuesday, June 14, 2016 at 4:41:48 PM UTC-5, Bart wrote:
> On 14/06/2016 22:29, supercat wrote:
> > On Tuesday, June 14, 2016 at 3:58:00 PM UTC-5, James R. Kuyper wrote:
> >> So there isn't really much of a reason for saying "It's too bad ...".
> >> For practical purposes, an implementation is allowed to generate code
> >> that treats the object lifetime as if it ended precisely when supercat
> >> wants it to end.
> >
> > My point was not about code generation, but rather to respond to the
> > comment about the desirability of scoping variables as narrowly as
> > possible.  Perhaps I should have used some word other than "temporary",
> > which has technical meaning, when what I meant to say was a variable which
> > is used briefly for some purpose but never again.  If I
> > want to do something like:
> >
> >     double dx = monster.x-player.x;
> >     double dy = monster.y-player.y
> >     double monster_distance = sqrt(dx*dx+dy*dy);
> >
> > and never need dx and dy after that, then their scope should ideally start
> > at the point of their declaration and end with the declaration of distance,
> > whereupon the *identifiers* could be freed up for other purposes.  While
> > one could use:
> 
> With gcc you can try this:
> 
>       double monster_distance = ({
>           double dx = monster.x-player.x;
>           double dy = monster.y-player.y;
>           sqrt(dx*dx+dy*dy);});

GCC's statement-functions are a useful feature, and I think it's
unfortunate that they have not been adopted into the Standard.  It
may be difficult for a single-pass compiler to generate efficient
code for them, but I don't think C11 is really designed to facilitate
single-pass compilation anymore anyhow.

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


#89119

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2016-06-15 00:25 +0100
Message-ID<87oa73xsi4.fsf@bsb.me.uk>
In reply to#89110
supercat@casperkitty.com writes:

> On Tuesday, June 14, 2016 at 4:41:48 PM UTC-5, Bart wrote:
<snip>
>> With gcc you can try this:
>> 
>>       double monster_distance = ({
>>           double dx = monster.x-player.x;
>>           double dy = monster.y-player.y;
>>           sqrt(dx*dx+dy*dy);});
>
> GCC's statement-functions are a useful feature, and I think it's
> unfortunate that they have not been adopted into the Standard.

I would call them block expressions because they are really not
functions (I'm not sure what gcc calls them).

I've always liked them but I would not use one in this example -- it
seems to be solving a non-problem for me.  I wonder if anyone ever
proposed that C should have them?

BCPL had a slightly more flexible version (with a return statement) but
they did not make it into B.  I wonder if C would have had them if they
had made the cut.

<snip>
-- 
Ben.

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


#89123

FromKeith Thompson <kst-u@mib.org>
Date2016-06-14 16:58 -0700
Message-ID<lna8in1fxw.fsf@kst-u.example.com>
In reply to#89119
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> supercat@casperkitty.com writes:
>> On Tuesday, June 14, 2016 at 4:41:48 PM UTC-5, Bart wrote:
> <snip>
>>> With gcc you can try this:
>>> 
>>>       double monster_distance = ({
>>>           double dx = monster.x-player.x;
>>>           double dy = monster.y-player.y;
>>>           sqrt(dx*dx+dy*dy);});
>>
>> GCC's statement-functions are a useful feature, and I think it's
>> unfortunate that they have not been adopted into the Standard.
>
> I would call them block expressions because they are really not
> functions (I'm not sure what gcc calls them).

gcc calls them "statement expressions".

https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/Statement-Exprs.html

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

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


#89138

FromDavid Brown <david.brown@hesbynett.no>
Date2016-06-15 09:28 +0200
Message-ID<njr036$6jc$1@dont-email.me>
In reply to#89119
On 15/06/16 01:25, Ben Bacarisse wrote:
> supercat@casperkitty.com writes:
> 
>> On Tuesday, June 14, 2016 at 4:41:48 PM UTC-5, Bart wrote:
> <snip>
>>> With gcc you can try this:
>>>
>>>       double monster_distance = ({
>>>           double dx = monster.x-player.x;
>>>           double dy = monster.y-player.y;
>>>           sqrt(dx*dx+dy*dy);});
>>
>> GCC's statement-functions are a useful feature, and I think it's
>> unfortunate that they have not been adopted into the Standard.
> 
> I would call them block expressions because they are really not
> functions (I'm not sure what gcc calls them).

The manual talks about "statement expressions", but does not appear
(AFAICS) to use that as a defining term for them.

> 
> I've always liked them but I would not use one in this example -- it
> seems to be solving a non-problem for me.  I wonder if anyone ever
> proposed that C should have them?

C++ has lambdas, which can (I think) do anything that could be done by
gcc's "statement expressions".  But I too have found this gcc extension
useful on occasion.

> 
> BCPL had a slightly more flexible version (with a return statement) but
> they did not make it into B.  I wonder if C would have had them if they
> had made the cut.
> 
> <snip>
> 

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


#89173

FromKeith Thompson <kst-u@mib.org>
Date2016-06-15 09:57 -0700
Message-ID<lnoa72z8xc.fsf@kst-u.example.com>
In reply to#89138
David Brown <david.brown@hesbynett.no> writes:
> On 15/06/16 01:25, Ben Bacarisse wrote:
[...]
>> I would call them block expressions because they are really not
>> functions (I'm not sure what gcc calls them).
>
> The manual talks about "statement expressions", but does not appear
> (AFAICS) to use that as a defining term for them.

The section of the gcc manual that discusses them is titled "Statement
Exprs".

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

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


#89136

FromDavid Brown <david.brown@hesbynett.no>
Date2016-06-15 09:23 +0200
Message-ID<njqvp0$5nh$1@dont-email.me>
In reply to#89099
On 14/06/16 23:29, supercat@casperkitty.com wrote:
> On Tuesday, June 14, 2016 at 3:58:00 PM UTC-5, James R. Kuyper wrote:
>> So there isn't really much of a reason for saying "It's too bad ...".
>> For practical purposes, an implementation is allowed to generate code
>> that treats the object lifetime as if it ended precisely when supercat
>> wants it to end.
> 
> My point was not about code generation, but rather to respond to the
> comment about the desirability of scoping variables as narrowly as
> possible.  Perhaps I should have used some word other than "temporary",
> which has technical meaning, when what I meant to say was a variable which
> is used briefly for some purpose but never again.  If I
> want to do something like:
> 
>     double dx = monster.x-player.x;
>     double dy = monster.y-player.y
>     double monster_distance = sqrt(dx*dx+dy*dy);
> 
> and never need dx and dy after that, then their scope should ideally start
> at the point of their declaration and end with the declaration of distance,
> whereupon the *identifiers* could be freed up for other purposes.  While
> one could use:
> 
>     double dx,dy
>     ...    
>     dx = monster.x-player.x;
>     dy = monster.y-player.y
>     double monster_distance = sqrt(dx*dx+dy*dy);
>     ...
>     dx = shot.x-player.x;
>     dy = shot.y-player.y
>     double shot_distance = sqrt(dx*dx+dy*dy);
> 
> or
> 
>     double monster_distance;
>     {
>       double dx = monster.x-player.x;
>       double dy = monster.y-player.y
>       monster_distance = sqrt(dx*dx+dy*dy);
>     }
>     double shot_distance;
>     {
>       double dx = shot.x-player.x;
>       double dy = shot.y-player.y
>       shot_distance = sqrt(dx*dx+dy*dy);
>     }
> 
> or
> 
>     double dx1 = monster.x-player.x;
>     double dy1 = monster.y-player.y
>     double monster_distance = sqrt(dx1*dx1+dy1*dy1);
>     ...
>     double dx2 = shot.x-player.x;
>     double dy2 = shot.y-player.y
>     double shot_distance = sqrt(dx2*dx2+dy2*dy2);
> 
> the first approach vastly over-extends the scope of dx and dy, the
> second creates monster_distance and shot_distance without any kind of
> meaningful initial value, and the third approach clutters up the scope
> with excessive variable names.
> 

I understand what you mean here.  All three versions here will give the
same generated code (assuming a reasonable compiler), so there is no
difference in the efficiency of the output.  But it would be nice if
there were a convenient way to avoid it.

The neatest way would be to simply allow

     double dx = monster.x-player.x;
     double dy = monster.y-player.y
     double monster_distance = sqrt(dx*dx+dy*dy);
     ...
     double dx = shot.x-player.x;
     double dy = shot.y-player.y
     double shot_distance = sqrt(dx*dx+dy*dy);

and say that a re-definition of "double dx" creates a new variable in a
new scope, just as if the second part were inside its own block.

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


#89139

FromRichard Heathfield <rjh@cpax.org.uk>
Date2016-06-15 08:35 +0100
Message-ID<njr0g1$7ul$1@dont-email.me>
In reply to#89136
On 15/06/16 08:23, David Brown wrote:

<snip>

> I understand what you mean here.  All three versions here will give the
> same generated code (assuming a reasonable compiler), so there is no
> difference in the efficiency of the output.  But it would be nice if
> there were a convenient way to avoid it.
>
> The neatest way would be to simply allow
>
>       double dx = monster.x-player.x;
>       double dy = monster.y-player.y
>       double monster_distance = sqrt(dx*dx+dy*dy);
>       ...
>       double dx = shot.x-player.x;
>       double dy = shot.y-player.y
>       double shot_distance = sqrt(dx*dx+dy*dy);
>
> and say that a re-definition of "double dx" creates a new variable in a
> new scope, just as if the second part were inside its own block.

Wouldn't it be even more elegant to have some kind of mechanism for 
abstracting the calculation into a /completely separate/ section of 
code, specifically for performing the function of calculating a 
distance? We might even call it a "function". I'm imagining a crazy, 
whacky kind of syntax like this for the "function":

double calc_distance(point a, point b)
{
   double dx = a.x - b.x;
   double dy = a.y - b.y;
   return sqrt(dx*dx - dy*dy);
}

Then, in your game code, you could, uh, what's a good word? Oh, okay, I 
think I've got it... You could /call/ the function, like this:

   double monster_distance = calc_distance(player, monster);
   double shot_distance    = calc_distance(player, shot);

and that would give you exactly what you need *without* having to change 
the language, *if only* C had some mechanism for providing these 
"functions".

Oh, hang on a second...

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

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


#89140

FromRichard Heathfield <rjh@cpax.org.uk>
Date2016-06-15 08:37 +0100
Message-ID<njr0j8$7ul$2@dont-email.me>
In reply to#89139
On 15/06/16 08:35, Richard Heathfield wrote:

<snip>

> double calc_distance(point a, point b)
> {
>    double dx = a.x - b.x;
>    double dy = a.y - b.y;
>    return sqrt(dx*dx - dy*dy);
> }


As an added bonus, if you get it wrong, you only need to fix it in one 
place. :-)

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

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


#89144

FromDavid Brown <david.brown@hesbynett.no>
Date2016-06-15 10:42 +0200
Message-ID<njr4ds$k7i$1@dont-email.me>
In reply to#89139
On 15/06/16 09:35, Richard Heathfield wrote:
> On 15/06/16 08:23, David Brown wrote:
> 
> <snip>
> 
>> I understand what you mean here.  All three versions here will give the
>> same generated code (assuming a reasonable compiler), so there is no
>> difference in the efficiency of the output.  But it would be nice if
>> there were a convenient way to avoid it.
>>
>> The neatest way would be to simply allow
>>
>>       double dx = monster.x-player.x;
>>       double dy = monster.y-player.y
>>       double monster_distance = sqrt(dx*dx+dy*dy);
>>       ...
>>       double dx = shot.x-player.x;
>>       double dy = shot.y-player.y
>>       double shot_distance = sqrt(dx*dx+dy*dy);
>>
>> and say that a re-definition of "double dx" creates a new variable in a
>> new scope, just as if the second part were inside its own block.
> 
> Wouldn't it be even more elegant to have some kind of mechanism for
> abstracting the calculation into a /completely separate/ section of
> code, specifically for performing the function of calculating a
> distance? We might even call it a "function". I'm imagining a crazy,
> whacky kind of syntax like this for the "function":
> 
> double calc_distance(point a, point b)
> {
>   double dx = a.x - b.x;
>   double dy = a.y - b.y;
>   return sqrt(dx*dx - dy*dy);
> }
> 
> Then, in your game code, you could, uh, what's a good word? Oh, okay, I
> think I've got it... You could /call/ the function, like this:
> 
>   double monster_distance = calc_distance(player, monster);
>   double shot_distance    = calc_distance(player, shot);
> 
> and that would give you exactly what you need *without* having to change
> the language, *if only* C had some mechanism for providing these
> "functions".
> 
> Oh, hang on a second...
> 

Yes, of course you might want to use functions for something like this.
 But sometimes extracting such cases to functions is messy and ugly -
you separate the logical flow of the code too much.  It's fine with a
nice generic "distance" function, but not for all cases.  It is even
worse if the duplicate code makes a lot of references to local variables
within the function - your extracted function then needs a dozen
parameters, some of them by value and some by pointer reference, and the
code duplication for calling the function is as bad as code duplication
for just doing the calculation inline.

The better solution in such cases might be some sort of local function
that has access to the function-local data, such as C++ lambdas or gcc
nested functions.  But those are not standard C.

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


#89165

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2016-06-15 13:28 +0100
Message-ID<871t3yy6to.fsf@bsb.me.uk>
In reply to#89144
David Brown <david.brown@hesbynett.no> writes:
<snip>
> The better solution in such cases might be some sort of local function
> that has access to the function-local data, such as C++ lambdas or gcc
> nested functions.  But those are not standard C.

Yes, I don't think I've ever written a non-trivial program in a language
that allows local function definitions when I haven't used them.  They
are a very useful code structuring tool.

(Lambdas are a more heavy-weight mechanism, but one can have even a very
limited kind of local function definition that is still useful in
organising code.)

-- 
Ben.

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


#89183

Fromsupercat@casperkitty.com
Date2016-06-15 11:41 -0700
Message-ID<1bb2b4e7-f0fc-48fe-acf2-c098c6ed5176@googlegroups.com>
In reply to#89136
On Wednesday, June 15, 2016 at 2:23:20 AM UTC-5, David Brown wrote:
> On 14/06/16 23:29, supercat wrote:
> > On Tuesday, June 14, 2016 at 3:58:00 PM UTC-5, James R. Kuyper wrote:
> >> So there isn't really much of a reason for saying "It's too bad ...".
> >> For practical purposes, an implementation is allowed to generate code
> >> that treats the object lifetime as if it ended precisely when supercat
> >> wants it to end.
> > 
> > My point was not about code generation, but rather to respond to the
> > comment about the desirability of scoping variables as narrowly as
> > possible.  Perhaps I should have used some word other than "temporary",
> > which has technical meaning, when what I meant to say was a variable which
> > is used briefly for some purpose but never again.  If I
> > want to do something like:
> > 
> >     double dx = monster.x-player.x;
> >     double dy = monster.y-player.y
> >     double monster_distance = sqrt(dx*dx+dy*dy);
> > 
> > and never need dx and dy after that, then their scope should ideally start
> > at the point of their declaration and end with the declaration of distance,
> > whereupon the *identifiers* could be freed up for other purposes.  While
> > one could use:
> > 
> >     double dx,dy
> >     ...    
> >     dx = monster.x-player.x;
> >     dy = monster.y-player.y
> >     double monster_distance = sqrt(dx*dx+dy*dy);
> >     ...
> >     dx = shot.x-player.x;
> >     dy = shot.y-player.y
> >     double shot_distance = sqrt(dx*dx+dy*dy);
> > 
> > or
> > 
> >     double monster_distance;
> >     {
> >       double dx = monster.x-player.x;
> >       double dy = monster.y-player.y
> >       monster_distance = sqrt(dx*dx+dy*dy);
> >     }
> >     double shot_distance;
> >     {
> >       double dx = shot.x-player.x;
> >       double dy = shot.y-player.y
> >       shot_distance = sqrt(dx*dx+dy*dy);
> >     }
> > 
> > or
> > 
> >     double dx1 = monster.x-player.x;
> >     double dy1 = monster.y-player.y
> >     double monster_distance = sqrt(dx1*dx1+dy1*dy1);
> >     ...
> >     double dx2 = shot.x-player.x;
> >     double dy2 = shot.y-player.y
> >     double shot_distance = sqrt(dx2*dx2+dy2*dy2);
> > 
> > the first approach vastly over-extends the scope of dx and dy, the
> > second creates monster_distance and shot_distance without any kind of
> > meaningful initial value, and the third approach clutters up the scope
> > with excessive variable names.
> > 
> 
> I understand what you mean here.  All three versions here will give the
> same generated code (assuming a reasonable compiler), so there is no
> difference in the efficiency of the output.  But it would be nice if
> there were a convenient way to avoid it.
> 
> The neatest way would be to simply allow
> 
>      double dx = monster.x-player.x;
>      double dy = monster.y-player.y
>      double monster_distance = sqrt(dx*dx+dy*dy);
>      ...
>      double dx = shot.x-player.x;
>      double dy = shot.y-player.y
>      double shot_distance = sqrt(dx*dx+dy*dy);
> 
> and say that a re-definition of "double dx" creates a new variable in a
> new scope, just as if the second part were inside its own block.

The way I'd like to see that handled would be to have different syntax for
assigning names to variables (containers into which values can be put)
versus values, and allow a name to be used for multiple values within a
scoping block provided that:

   1. The name was not used for anything other than a value declaration,
      and...

   2. Except in cases where both blocks of an "if/else" assign the same
      name to values of the same type, semantics would be unaffected if
      some or all such declarations were to create distinct variables.

That would make it possible to read backward in source-code order from a
place where an identifier was used to find where its value was set, and
know that the variable cannot hold a value that was left over from
some code that was executed earlier.

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


Page 3 of 5 — ← Prev page 1 2 [3] 4 5  Next page →

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


csiph-web