Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #88991 > unrolled thread
| Started by | G G <gdotone@gmail.com> |
|---|---|
| First post | 2016-06-12 16:21 -0700 |
| Last post | 2016-06-16 21:39 -0700 |
| Articles | 20 on this page of 86 — 20 participants |
Back to article view | Back to comp.lang.c
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 →
| From | John Bode <jfbode1029@gmail.com> |
|---|---|
| Date | 2016-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]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2016-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]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2016-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]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2016-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-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]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2016-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]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2016-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-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]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2016-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-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]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2016-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]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2016-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-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