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


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

Do variables need to be initialized?

Started byfl <rxjwg98@gmail.com>
First post2015-06-01 16:48 -0700
Last post2015-06-05 10:56 -0700
Articles 20 on this page of 41 — 15 participants

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


Contents

  Do variables need to be initialized? fl <rxjwg98@gmail.com> - 2015-06-01 16:48 -0700
    Re: Do variables need to be initialized? Richard Heathfield <rjh@cpax.org.uk> - 2015-06-02 00:55 +0100
      Re: Do variables need to be initialized? Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2015-06-01 18:22 -0600
        Re: Do variables need to be initialized? Keith Thompson <kst-u@mib.org> - 2015-06-02 08:05 -0700
          Re: Do variables need to be initialized? Tim Rentsch <txr@alumni.caltech.edu> - 2015-07-11 08:07 -0700
            Re: Do variables need to be initialized? Keith Thompson <kst-u@mib.org> - 2015-07-11 16:47 -0700
              Re: Do variables need to be initialized? Tim Rentsch <txr@alumni.caltech.edu> - 2015-07-15 07:42 -0700
        Re: Do variables need to be initialized? Tim Rentsch <txr@alumni.caltech.edu> - 2015-07-11 08:03 -0700
    Re: Do variables need to be initialized? David Brown <david.brown@hesbynett.no> - 2015-06-02 09:15 +0200
      Re: Do variables need to be initialized? Tim Rentsch <txr@alumni.caltech.edu> - 2015-07-11 08:09 -0700
    Re: Do variables need to be initialized? David Kleinecke <dkleinecke@gmail.com> - 2015-06-03 09:30 -0700
      Re: Do variables need to be initialized? gwowen <gwowen@gmail.com> - 2015-06-03 09:41 -0700
        Re: Do variables need to be initialized? David Kleinecke <dkleinecke@gmail.com> - 2015-06-04 10:17 -0700
          Re: Do variables need to be initialized? Stephen Sprunk <stephen@sprunk.org> - 2015-06-05 11:10 -0500
            Re: Do variables need to be initialized? Bartc <bc@freeuk.com> - 2015-06-05 18:22 +0100
              Re: Do variables need to be initialized? Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2015-06-05 20:54 -0600
                Re: Do variables need to be initialized? Ian Collins <ian-news@hotmail.com> - 2015-06-06 15:49 +1200
                  Re: Do variables need to be initialized? Dr Nick <nospam-4@temporary-address.org.uk> - 2015-06-06 08:42 +0100
                    Re: Do variables need to be initialized? Keith Thompson <kst-u@mib.org> - 2015-06-06 13:11 -0700
                      Re: Do variables need to be initialized? Dr Nick <nospam-4@temporary-address.org.uk> - 2015-06-07 16:58 +0100
                  Re: Do variables need to be initialized? Bartc <bc@freeuk.com> - 2015-06-06 11:01 +0100
                    Re: Do variables need to be initialized? Ian Collins <ian-news@hotmail.com> - 2015-06-07 09:07 +1200
                  Re: Do variables need to be initialized? Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2015-06-06 15:06 -0600
                    Re: Do variables need to be initialized? gwowen <gwowen@gmail.com> - 2015-06-08 05:39 -0700
                      Re: Do variables need to be initialized? Bartc <bc@freeuk.com> - 2015-06-08 14:10 +0100
                        Re: Do variables need to be initialized? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-06-08 14:21 +0100
                          Re: Do variables need to be initialized? Bartc <bc@freeuk.com> - 2015-06-08 14:34 +0100
                            Re: Do variables need to be initialized? David Brown <david.brown@hesbynett.no> - 2015-06-08 16:51 +0200
                              Re: Do variables need to be initialized? Richard Heathfield <rjh@cpax.org.uk> - 2015-06-08 16:15 +0100
                              Re: Do variables need to be initialized? Bartc <bc@freeuk.com> - 2015-06-08 17:31 +0100
                                Re: Do variables need to be initialized? Ian Collins <ian-news@hotmail.com> - 2015-06-09 08:06 +1200
                                  Re: Do variables need to be initialized? Bartc <bc@freeuk.com> - 2015-06-08 22:58 +0100
                            Re: Do variables need to be initialized? Keith Thompson <kst-u@mib.org> - 2015-06-08 08:27 -0700
                        Re: Do variables need to be initialized? gwowen <gwowen@gmail.com> - 2015-06-08 08:01 -0700
              Re: Do variables need to be initialized? Stephen Sprunk <stephen@sprunk.org> - 2015-06-06 11:11 -0500
                Re: Do variables need to be initialized? Bartc <bc@freeuk.com> - 2015-06-06 19:09 +0100
                  Re: Do variables need to be initialized? Robert Wessel <robertwessel2@yahoo.com> - 2015-06-06 13:57 -0500
                    Re: Do variables need to be initialized? Keith Thompson <kst-u@mib.org> - 2015-06-06 13:52 -0700
                      Re: Do variables need to be initialized? James Kuyper <jameskuyper@verizon.net> - 2015-06-06 20:57 -0400
                  Re: Do variables need to be initialized? Stephen Sprunk <stephen@sprunk.org> - 2015-06-10 14:33 -0500
            Re: Do variables need to be initialized? Keith Thompson <kst-u@mib.org> - 2015-06-05 10:56 -0700

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


#63007

FromBartc <bc@freeuk.com>
Date2015-06-06 11:01 +0100
Message-ID<mkugbv$v1h$1@dont-email.me>
In reply to#63004
On 06/06/2015 04:49, Ian Collins wrote:
> Joe Pfeiffer wrote:
>>> On 05/06/2015 17:10, Stephen Sprunk wrote:
>>>
>>>> mixing declarations and
>>>> statements is an obvious improvement.
>>
>> When mixing became possible I tried it on a couple of projects and
>> concluded I hate it.  I want to be able to look in one place for my
>> variables' declarations, not have to go searching through the function.
>
> If you have to search, the function is too long.

But if the function is short, what is the advantage of having 
declarations in arbitrary places, or even of having nested declarations 
within blocks?

And even short functions can have complicated looking lines (I suppose 
your solution is to factor even more, but then there is even less need 
to declare things in random locations).

But, sometimes you have int a,b; two thirds through the function, and 
a=b; shortly after. Then you decide you need a=b; earlier on as well. 
Now, you have to keep schlepping the declarations around the function as 
the first appearance of each name in the code changes!

And if you forget to do so, the declaration occurs after the use, the 
code will still compile if there more file-scope names that match. But 
there's now a non-obvious bug.

I really can't see any justification for this awful practice at all 
(excepting as 'for (int i=0....)', but that's the only code example). 
Especially when other people have to read the code.

This is some real code (not mine). /Fortunately/, most C open source 
projects seem to have adopted the style of declaring all the local 
variables at the start of a function.

Notice this function isn't particularly long or complicated, so would 
not benefit from being broken up. As it is, I can quickly look through 
the index of variables (the 'cast-list') at the beginning to see what's 
what. But imagine what it would look like if the declarations were 
dispersed through the code?

int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
{
     char *Identifier;
     struct ValueType *BasicType;
     struct ValueType *Typ;
     struct Value *NewVariable = NULL;
     int IsStatic = FALSE;
     int FirstVisit = FALSE;
     Picoc *pc = Parser->pc;

     TypeParseFront(Parser, &BasicType, &IsStatic);
     do
     {
         TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier);
         if ((Token != TokenVoidType && Token != TokenStructType && 
Token != TokenUnionType && Token != TokenEnumType) && Identifier == 
pc->StrEmpty)
             ProgramFail(Parser, "identifier expected");

         if (Identifier != pc->StrEmpty)
         {
             /* handle function definitions */
             if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket)
             {
                 ParseFunctionDefinition(Parser, Typ, Identifier);
                 return FALSE;
             }
             else
             {
                 if (Typ == &pc->VoidType && Identifier != pc->StrEmpty)
                     ProgramFail(Parser, "can't define a void variable");

                 if (Parser->Mode == RunModeRun || Parser->Mode == 
RunModeGoto)
                     NewVariable = 
VariableDefineButIgnoreIdentical(Parser, Identifier, Typ, IsStatic, 
&FirstVisit);

                 if (LexGetToken(Parser, NULL, FALSE) == TokenAssign)
                 {
                     /* we're assigning an initial value */
                     LexGetToken(Parser, NULL, TRUE);
                     ParseDeclarationAssignment(Parser, NewVariable, 
!IsStatic || FirstVisit);
                 }
             }
         }

         Token = LexGetToken(Parser, NULL, FALSE);
         if (Token == TokenComma)
             LexGetToken(Parser, NULL, TRUE);

     } while (Token == TokenComma);

     return TRUE;
}

-- 
Bartc

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


#63030

FromIan Collins <ian-news@hotmail.com>
Date2015-06-07 09:07 +1200
Message-ID<cth5p5Fn0m1U1@mid.individual.net>
In reply to#63007
Bartc wrote:
> On 06/06/2015 04:49, Ian Collins wrote:
>> Joe Pfeiffer wrote:
>>>> On 05/06/2015 17:10, Stephen Sprunk wrote:
>>>>
>>>>> mixing declarations and
>>>>> statements is an obvious improvement.
>>>
>>> When mixing became possible I tried it on a couple of projects and
>>> concluded I hate it.  I want to be able to look in one place for my
>>> variables' declarations, not have to go searching through the function.
>>
>> If you have to search, the function is too long.
>
> But if the function is short, what is the advantage of having
> declarations in arbitrary places, or even of having nested declarations
> within blocks?

For one you don have to worry about whether or not to initialise variables!

> And even short functions can have complicated looking lines (I suppose
> your solution is to factor even more, but then there is even less need
> to declare things in random locations).

One of my pet hates is complicated expressions in conditionals. 
Assigning the value of the expression to a local const (or building the 
value up in steps with several) makes the code easier to read and debug. 
  Declaring these anywhere other that the point of first use makes the 
code harder to read.

> But, sometimes you have int a,b; two thirds through the function, and
> a=b; shortly after. Then you decide you need a=b; earlier on as well.
> Now, you have to keep schlepping the declarations around the function as
> the first appearance of each name in the code changes!

Not something I can recall doing.

> And if you forget to do so, the declaration occurs after the use, the
> code will still compile if there more file-scope names that match. But
> there's now a non-obvious bug.

Just a breakdown in process.

> I really can't see any justification for this awful practice at all
> (excepting as 'for (int i=0....)', but that's the only code example).
> Especially when other people have to read the code.

Consider the situation I mentioned above.

> This is some real code (not mine). /Fortunately/, most C open source
> projects seem to have adopted the style of declaring all the local
> variables at the start of a function.

Given that rule, consider how the code would look if the function were 
to start with some precondition checks, would you declare the local 
variables before or after them?

-- 
Ian Collins

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


#63029

FromJoe Pfeiffer <pfeiffer@cs.nmsu.edu>
Date2015-06-06 15:06 -0600
Message-ID<1blhfwh7i2.fsf@pfeifferfamily.net>
In reply to#63004
Ian Collins <ian-news@hotmail.com> writes:

> Joe Pfeiffer wrote:
>>> On 05/06/2015 17:10, Stephen Sprunk wrote:
>>>
>>>> mixing declarations and
>>>> statements is an obvious improvement.
>>
>> When mixing became possible I tried it on a couple of projects and
>> concluded I hate it.  I want to be able to look in one place for my
>> variables' declarations, not have to go searching through the function.
>
> If you have to search, the function is too long.

If the search is non-trivial, the function is too long.  If the
variables aren't all declared together, you still have to scan the
20-line function to figure out where they are.  That search is trivial,
but still present.

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


#63068

Fromgwowen <gwowen@gmail.com>
Date2015-06-08 05:39 -0700
Message-ID<4450dd92-34e2-47fd-a5f7-ad5da054057a@googlegroups.com>
In reply to#63029
On Saturday, June 6, 2015 at 10:06:22 PM UTC+1, Joe Pfeiffer wrote:

> If the search is non-trivial, the function is too long.  If the
> variables aren't all declared together, you still have to scan the
> 20-line function to figure out where they are.  That search is trivial,
> but still present.

Nope.  If the function is short, and declarations are at point-of-first-use then the majority of time the search is non existent - the declaration is right there within a line or two of the use.

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


#63070

FromBartc <bc@freeuk.com>
Date2015-06-08 14:10 +0100
Message-ID<ml446m$bb1$1@dont-email.me>
In reply to#63068
On 08/06/2015 13:39, gwowen wrote:
> On Saturday, June 6, 2015 at 10:06:22 PM UTC+1, Joe Pfeiffer wrote:
>
>> If the search is non-trivial, the function is too long.  If the
>> variables aren't all declared together, you still have to scan the
>> 20-line function to figure out where they are.  That search is trivial,
>> but still present.
>
> Nope.  If the function is short, and declarations are at point-of-first-use then the majority of time the search is non existent - the declaration is right there within a line or two of the use.
>

Which expression is easier to take in:

  double a,b,c;

  x=(-b + sqrt(b*b - 4*a*c)) / (2*a);

or:

  double x = (- double b + sqrt(b*b - 4 * double a*double c) / (2*a);

(I know this is not C syntax but it's the same principle of mixing 
things up that shouldn't be mixed up.)

Take another example:

  point *p1 *p2, *p3;

Here, I don't really need to write anything further, as that declaration 
is sufficient: those p1, p2, and p3 variables are clearly related. That 
relationship is lost if the declarations are split up because each is 
first used in a different place.

I can also tell from this that they only go up to p3, and there isn't a 
p4 lurking somewhere else.

Also, if I need change from point* to point2d* for example, it's a lot 
easier when the declarations are grouped in one place.

 > Nope.  If the function is short, and declarations are at 
point-of-first-use then the majority of time the search is non existent

What is a short function? Real code is full of long variable names 
(often similar to each other), comments, conditional code, strange brace 
styles, all sorts of junk that can make it easy to miss something even 
when the function is 'short'.

 >the declaration is right there within a line or two of the use.

Only if a variable is only used once or twice within a few lines of its 
declaration.

Anyway you can't use this technique with parameter names; people seem to 
cope. Unless you suggest parameter names should only be used within the 
first three lines of the function.

-- 
Bartc

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


#63071

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-06-08 14:21 +0100
Message-ID<87mw0a9vz6.fsf@bsb.me.uk>
In reply to#63070
Bartc <bc@freeuk.com> writes:

> On 08/06/2015 13:39, gwowen wrote:
>> On Saturday, June 6, 2015 at 10:06:22 PM UTC+1, Joe Pfeiffer wrote:
>>
>>> If the search is non-trivial, the function is too long.  If the
>>> variables aren't all declared together, you still have to scan the
>>> 20-line function to figure out where they are.  That search is trivial,
>>> but still present.
>>
>> Nope.  If the function is short, and declarations are at
>> point-of-first-use then the majority of time the search is non
>> existent - the declaration is right there within a line or two of
>> the use.
>>
>
> Which expression is easier to take in:
>
>  double a,b,c;
>
>  x=(-b + sqrt(b*b - 4*a*c)) / (2*a);
>
> or:
>
>  double x = (- double b + sqrt(b*b - 4 * double a*double c) / (2*a);
>
> (I know this is not C syntax but it's the same principle of mixing
> things up that shouldn't be mixed up.)

<jaw drops>  Really?  You support your argument with some made up
syntax that has nothing to do with the case being discussed?

> Take another example:
>
>  point *p1 *p2, *p3;

(missing ',')

> Here, I don't really need to write anything further, as that
> declaration is sufficient: those p1, p2, and p3 variables are clearly
> related. That relationship is lost if the declarations are split up
> because each is first used in a different place.

Did anyone say that you *have* to separate related declarations?  Your
argument seems to be against making use of the permission to delay
declaration until first use, but no one is saying that you must do so in
every case.

<snip>
-- 
Ben.

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


#63072

FromBartc <bc@freeuk.com>
Date2015-06-08 14:34 +0100
Message-ID<ml45i8$gmn$1@dont-email.me>
In reply to#63071
On 08/06/2015 14:21, Ben Bacarisse wrote:
> Bartc <bc@freeuk.com> writes:
>
>> On 08/06/2015 13:39, gwowen wrote:
>>> On Saturday, June 6, 2015 at 10:06:22 PM UTC+1, Joe Pfeiffer wrote:
>>>
>>>> If the search is non-trivial, the function is too long.  If the
>>>> variables aren't all declared together, you still have to scan the
>>>> 20-line function to figure out where they are.  That search is trivial,
>>>> but still present.
>>>
>>> Nope.  If the function is short, and declarations are at
>>> point-of-first-use then the majority of time the search is non
>>> existent - the declaration is right there within a line or two of
>>> the use.
>>>
>>
>> Which expression is easier to take in:
>>
>>   double a,b,c;
>>
>>   x=(-b + sqrt(b*b - 4*a*c)) / (2*a);
>>
>> or:
>>
>>   double x = (- double b + sqrt(b*b - 4 * double a*double c) / (2*a);
>>
>> (I know this is not C syntax but it's the same principle of mixing
>> things up that shouldn't be mixed up.)
>
> <jaw drops>  Really?  You support your argument with some made up
> syntax that has nothing to do with the case being discussed?

You can't see that both introduce clutter that is going to affect 
readability? If I'm trying to grasp an algorithm expressed by the code, 
then it's going to be easier without arbitrary declarations all over the 
place. (An int a=0; will also move that assignment 4 characters to the 
right, out of the line of the other assignments.)

>
>> Take another example:
>>
>>   point *p1 *p2, *p3;
>
> (missing ',')
>
>> Here, I don't really need to write anything further, as that
>> declaration is sufficient: those p1, p2, and p3 variables are clearly
>> related. That relationship is lost if the declarations are split up
>> because each is first used in a different place.
>
> Did anyone say that you *have* to separate related declarations?  Your
> argument seems to be against making use of the permission to delay
> declaration until first use, but no one is saying that you must do so in
> every case.

Sure, people can use either style. However if there is a possibility 
that there are other declarations buried in the code (someone decided 
they will try a p4, declare it in-place, then forgot about it) then it 
is something you have to consider.

So you see a *p3 at the top, see a p3 used in the code, and think that's 
it. Then you discover another p3 in a nested block! Possible of a 
different type too.

I think most people will use my preferred style, but an awful lot 
apparently think it's OK to declare names in arbitrary, unexpected places.

-- 
Bartc

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


#63074

FromDavid Brown <david.brown@hesbynett.no>
Date2015-06-08 16:51 +0200
Message-ID<ml4a2j$2vf$1@dont-email.me>
In reply to#63072
On 08/06/15 15:34, Bartc wrote:
> On 08/06/2015 14:21, Ben Bacarisse wrote:
>> Bartc <bc@freeuk.com> writes:
>>
>>> On 08/06/2015 13:39, gwowen wrote:
>>>> On Saturday, June 6, 2015 at 10:06:22 PM UTC+1, Joe Pfeiffer wrote:
>>>>
>>>>> If the search is non-trivial, the function is too long.  If the
>>>>> variables aren't all declared together, you still have to scan the
>>>>> 20-line function to figure out where they are.  That search is
>>>>> trivial,
>>>>> but still present.
>>>>
>>>> Nope.  If the function is short, and declarations are at
>>>> point-of-first-use then the majority of time the search is non
>>>> existent - the declaration is right there within a line or two of
>>>> the use.
>>>>
>>>
>>> Which expression is easier to take in:
>>>
>>>   double a,b,c;
>>>
>>>   x=(-b + sqrt(b*b - 4*a*c)) / (2*a);
>>>
>>> or:
>>>
>>>   double x = (- double b + sqrt(b*b - 4 * double a*double c) / (2*a);
>>>
>>> (I know this is not C syntax but it's the same principle of mixing
>>> things up that shouldn't be mixed up.)
>>
>> <jaw drops>  Really?  You support your argument with some made up
>> syntax that has nothing to do with the case being discussed?
> 
> You can't see that both introduce clutter that is going to affect
> readability? If I'm trying to grasp an algorithm expressed by the code,
> then it's going to be easier without arbitrary declarations all over the
> place. (An int a=0; will also move that assignment 4 characters to the
> right, out of the line of the other assignments.)

Putting random illegal identifiers in the middle of an expression
obviously adds clutter.  Putting a perfectly legal declaration at the
start is a common way of writing code:

double x = (-b + sqrt(b*b - 4*a*c)) / (2*a);

Adding that "double" is not "introducing clutter".

And yes, it moves the assignment a bit to the right - but assignments
are not (normally) in line anyway.

It is common practice to declare variables (and functions, types, etc.)
as close as conveniently possible to where you are going to use them.
This is considered good programming practice - you minimise scope and
lifetime of the variables.  And in some languages (notably C++) where
the definition plus assignment is not the same as an initialising
definition, there can be significant differences in where and how you
define the variables.

It is fine that /you/, in your personal opinion, do not like to mix
declarations and statements.  But you are simply wrong in making
sweeping statements about how "awful" this practice is.  Many other
people find it helps when writing clear, concise code.

> 
>>
>>> Take another example:
>>>
>>>   point *p1 *p2, *p3;
>>
>> (missing ',')
>>
>>> Here, I don't really need to write anything further, as that
>>> declaration is sufficient: those p1, p2, and p3 variables are clearly
>>> related. That relationship is lost if the declarations are split up
>>> because each is first used in a different place.

No, the only "clear relationship" between these variables is that they
are defined at the same place in the code.  Since that information is of
no value, nothing is lost by defining them elsewhere in the code.

>>
>> Did anyone say that you *have* to separate related declarations?  Your
>> argument seems to be against making use of the permission to delay
>> declaration until first use, but no one is saying that you must do so in
>> every case.
> 
> Sure, people can use either style. However if there is a possibility
> that there are other declarations buried in the code (someone decided
> they will try a p4, declare it in-place, then forgot about it) then it
> is something you have to consider.

This would only be an issue if you imagined that writing "point *p1,
*p2, *p3" implies that there is no "point *p4".

> 
> So you see a *p3 at the top, see a p3 used in the code, and think that's
> it. Then you discover another p3 in a nested block! Possible of a
> different type too.

There's no problem doing that.  Mixing declarations and code and using
block-local variables helps keep scopes minimal.  This makes it much
easier to be sure of exactly what "p3" is at any time.  It doesn't
matter if there is another "p3" somewhere else in the function - you can
see immediately what /this/ "p3" is, and you don't have to jump around
in the code to find it.

(Normally it's a good idea to keep names separate, but that's just
standard practice of writing clear code.)

> 
> I think most people will use my preferred style, but an awful lot
> apparently think it's OK to declare names in arbitrary, unexpected places.
> 

I think you have strong opinions about your style, because you haven't
really thought about alternatives - and you are generalising your own
ideas to "most people" without any justification.

(I have been guilty of that sin on enough occasions to recognize it here!)

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


#63076

FromRichard Heathfield <rjh@cpax.org.uk>
Date2015-06-08 16:15 +0100
Message-ID<ml4bg3$8vt$1@dont-email.me>
In reply to#63074
On 08/06/15 15:51, David Brown wrote:

<snip>

> double x = (-b + sqrt(b*b - 4*a*c)) / (2*a);
>
> Adding that "double" is not "introducing clutter".

Disclaimer: in C, my own preference is to avoid mixed declarations and 
code, but it isn't for reducing clutter. (In C++, I mix them freely.)

Having said that, I must agree with you that adding the double is not 
the source of the clutter. The source of the clutter is... everything else!

The statement *should* read:

double x = quadroot(a, b, c);

<snip>

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


#63085

FromBartc <bc@freeuk.com>
Date2015-06-08 17:31 +0100
Message-ID<ml4fvb$s30$1@dont-email.me>
In reply to#63074
On 08/06/2015 15:51, David Brown wrote:
> On 08/06/15 15:34, Bartc wrote:

>> You can't see that both introduce clutter that is going to affect
>> readability?

> It is common practice to declare variables (and functions, types, etc.)
> as close as conveniently possible to where you are going to use them.
> This is considered good programming practice - you minimise scope and
> lifetime of the variables.

Sure. You do that by using variables within the same function! If the 
declarations at top seem too remote from their use later in the 
function, /then/ maybe the function might be too big.

All I'm saying is that interspersing declarations alters the 'lines' of 
the code adversely.

IMO.

-- 
Bartc

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


#63093

FromIan Collins <ian-news@hotmail.com>
Date2015-06-09 08:06 +1200
Message-ID<ctmav1F238tU1@mid.individual.net>
In reply to#63085
Bartc wrote:
> On 08/06/2015 15:51, David Brown wrote:
>> On 08/06/15 15:34, Bartc wrote:
>
>>> You can't see that both introduce clutter that is going to affect
>>> readability?
>
>> It is common practice to declare variables (and functions, types, etc.)
>> as close as conveniently possible to where you are going to use them.
>> This is considered good programming practice - you minimise scope and
>> lifetime of the variables.
>
> Sure. You do that by using variables within the same function! If the
> declarations at top seem too remote from their use later in the
> function, /then/ maybe the function might be too big.
>
> All I'm saying is that interspersing declarations alters the 'lines' of
> the code adversely.

Care to address the examples I mentioned a couple of days ago?

-- 
Ian Collins

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


#63097

FromBartc <bc@freeuk.com>
Date2015-06-08 22:58 +0100
Message-ID<ml534i$abg$1@dont-email.me>
In reply to#63093
On 08/06/2015 21:06, Ian Collins wrote:
> Bartc wrote:
>> On 08/06/2015 15:51, David Brown wrote:
>>> On 08/06/15 15:34, Bartc wrote:
>>
>>>> You can't see that both introduce clutter that is going to affect
>>>> readability?
>>
>>> It is common practice to declare variables (and functions, types, etc.)
>>> as close as conveniently possible to where you are going to use them.
>>> This is considered good programming practice - you minimise scope and
>>> lifetime of the variables.
>>
>> Sure. You do that by using variables within the same function! If the
>> declarations at top seem too remote from their use later in the
>> function, /then/ maybe the function might be too big.
>>
>> All I'm saying is that interspersing declarations alters the 'lines' of
>> the code adversely.
>
> Care to address the examples I mentioned a couple of days ago?

OK (I don't view the group in threaded mode so tend to lose track).

I think I drafted a reply then cancelled because one of your examples 
(splitting a complex expression into smaller units each stored in a 
local temporary variable) was a good one and I couldn't really shoot it 
down.

But even then, declaring them like this:

   { int t1, t2;

     t1 = ...;
     t2 = ...;
     if (....)

is not that bad, if they are at least declared at the top of a block. 
What I don't like is a sequence of ordinary statements, assignments, 
function calls, and then suddenly a declaration:

    a = b+c;
    fn(0,10);
    int t1;
    ...

because it looks out of place. Although I expect you will use temps like 
this:

   ...
   int t1 = <subexpr>;
   int t2 = <subexpr>;
   ...

I would still just declare them at the top of the function (then you can 
re-use t1 and t2 instead of having to declare a t1 and a t2 inside a 
number of blocks).

(I remember I have my own language and compiler too. I've just checked 
it and that also allows declarations anywhere! I'll have to take care of 
it; I think it was easier to just allow that than to prohibit it.

In that case, the positioning actually doesn't matter, as the scope will 
always be the entire function body (there are no block scopes**). In C 
the scope ranges from point of declaration, to the end of the block or 
function. Still it looks odd, in C being the equivalent of:

   a = b+c;
   int a,b,c;

with the a,b,c in the expression being declared on the next line.

(**This language is a little different in allowing certain names inside 
a function (not parameters or auto variables) to be accessed from 
outside. So if a name 'a' is declared in function 'fn', I can access it 
from outside as fn.a. Hence no block scopes as blocks don't have names 
and there is no access path.))

-- 
Bartc

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


#63077

FromKeith Thompson <kst-u@mib.org>
Date2015-06-08 08:27 -0700
Message-ID<87wpzeqkyp.fsf@kst-u.example.com>
In reply to#63072
Bartc <bc@freeuk.com> writes:
[...]
> So you see a *p3 at the top, see a p3 used in the code, and think
> that's it. Then you discover another p3 in a nested block! Possible of
> a different type too.

If you define two objects, both called "p3", with different types,
in nested scopes, then you've got serious problems even if you
don't mix declarations and statements.  So don't do that.

> I think most people will use my preferred style, but an awful lot
> apparently think it's OK to declare names in arbitrary, unexpected
> places.

No, nobody thinks that.  A lot of people think it's OK to declare
names in non-arbitrary expected places that don't happen to be at
the top of a block.

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


#63075

Fromgwowen <gwowen@gmail.com>
Date2015-06-08 08:01 -0700
Message-ID<6736b1c5-4489-4b52-b849-004d335d2315@googlegroups.com>
In reply to#63070
On Monday, June 8, 2015 at 2:11:05 PM UTC+1, Bart wrote:
> Which expression is easier to take in:
> 
>   double a,b,c;
> 
>   x=(-b + sqrt(b*b - 4*a*c)) / (2*a);
> 
> or:
> 
>   double x = (- double b + sqrt(b*b - 4 * double a*double c) / (2*a);

Shakes head sadly.... 

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


#63016

FromStephen Sprunk <stephen@sprunk.org>
Date2015-06-06 11:11 -0500
Message-ID<mkv615$n3r$1@dont-email.me>
In reply to#62997
On 05-Jun-15 12:22, Bartc wrote:
> On 05/06/2015 17:10, Stephen Sprunk wrote:
>> On 04-Jun-15 12:17, David Kleinecke wrote:
>>> One reason it was silly is that mixing changes nothing significant.
>>
>> AIUI, early compilers worked line-by-line, and they needed all the
>> declarations in one place so they could set up the stack frame before
>> translating the following statements into code.
> 
> That seems to be still the case, in that functions need to be declared
> before use (or at least, will cause problems if they're not).

That's because you need to know the argument and return types to
properly generate the code to call the function.

>> If a declaration came later, then there would be no space left in 
>> the stack frame to put the variable, and they couldn't go back and 
>> increase the frame size because they'd already output the frame 
>> setup code--and the code in between that assumed a particular
>> frame size.
> 
> That sounds very unlikely, unless somehow all the code for one
> function didn't fit into memory. How did they manage to do a forward
> jump without knowing what the offset was going to be? Same sort of
> thing, and actually harder than the frame size problem

You emit a jump to a label, and it's the assembler's and/or linker's job
to replace that label with the correct address.

>> mixing declarations and statements is an obvious improvement.
> 
> In some people's view. Not in others'. Take file-scope variables and 
> macros and other declarations usually placed before all the function 
> definitions. Now imagine them disseminated throughout the file,
> placed just before the first function they are referenced. It would
> look terrible.

I've seen that, and I agree it looks terrible.  AFAIK, there has never
been a rule requiring those all be at the top, so that's a matter of an
evolved convention, which is distinct from the matter at hand.

> So why is untidily mixing up declarations and statements in the
> function body a good one? Also, what happens here:
> 
> int a=1,b,c;
> 
> if (a==1) {
>    a=2;
>    b=a;
>    int a=3;
>    c=a;
> }
> 
> which a is which in that inner block?

I have no clue; I'm sure the Standard could tell us, but as a general
rule, if I have to look something up in the Standard to figure out what
it means, the code is sufficiently unclear to fail a code review.

OTOH, if the declarations are all at the top of a function, then you may
have forgotten what they are by the time they're used.  That generally
indicates your function is too long, but sometimes it's unavoidable.

All of that said, I rarely mix declarations and statements except for
the (very useful) case of loop variables, e.g. "for (int i=...".  IMHO,
that alone makes this change a useful improvement, even if one doesn't
take advantage of it in any other circumstances.

S

-- 
Stephen Sprunk         "God does not play dice."  --Albert Einstein
CCIE #3723         "God is an inveterate gambler, and He throws the
K5SSS        dice at every possible opportunity." --Stephen Hawking

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


#63021

FromBartc <bc@freeuk.com>
Date2015-06-06 19:09 +0100
Message-ID<mkvcv9$jji$1@dont-email.me>
In reply to#63016
On 06/06/2015 17:11, Stephen Sprunk wrote:
> On 05-Jun-15 12:22, Bartc wrote:
>> On 05/06/2015 17:10, Stephen Sprunk wrote:
>>> On 04-Jun-15 12:17, David Kleinecke wrote:
>>>> One reason it was silly is that mixing changes nothing significant.
>>>
>>> AIUI, early compilers worked line-by-line, and they needed all the
>>> declarations in one place so they could set up the stack frame before
>>> translating the following statements into code.
>>
>> That seems to be still the case, in that functions need to be declared
>> before use (or at least, will cause problems if they're not).
>
> That's because you need to know the argument and return types to
> properly generate the code to call the function.

That can't have been the actual reason for decades. It's unlikely that 
final code will be generated for a function before the rest of the file 
has been scanned.

But C compilers still seem happy to generate code for a non-existent 
function that they've not had sight of at all; gcc compiles this with no 
problem:

int main(void) {
      anyfunction(10,20,30.9);
}

It just seems incredibly odd that it can process calls for functions it 
knows nothing about, and may not actually exist, or exist but with a 
totally different signature that will probably cause the program to 
crash, but it can't do so for an actual function that is fully defined 
20 lines further on in the file!


-- 
Bartc

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


#63022

FromRobert Wessel <robertwessel2@yahoo.com>
Date2015-06-06 13:57 -0500
Message-ID<2hg6na9jlu1jpcan79nqukimofv6h4c0rl@4ax.com>
In reply to#63021
On Sat, 06 Jun 2015 19:09:56 +0100, Bartc <bc@freeuk.com> wrote:

>On 06/06/2015 17:11, Stephen Sprunk wrote:
>> On 05-Jun-15 12:22, Bartc wrote:
>>> On 05/06/2015 17:10, Stephen Sprunk wrote:
>>>> On 04-Jun-15 12:17, David Kleinecke wrote:
>>>>> One reason it was silly is that mixing changes nothing significant.
>>>>
>>>> AIUI, early compilers worked line-by-line, and they needed all the
>>>> declarations in one place so they could set up the stack frame before
>>>> translating the following statements into code.
>>>
>>> That seems to be still the case, in that functions need to be declared
>>> before use (or at least, will cause problems if they're not).
>>
>> That's because you need to know the argument and return types to
>> properly generate the code to call the function.
>
>That can't have been the actual reason for decades. It's unlikely that 
>final code will be generated for a function before the rest of the file 
>has been scanned.
>
>But C compilers still seem happy to generate code for a non-existent 
>function that they've not had sight of at all; gcc compiles this with no 
>problem:
>
>int main(void) {
>      anyfunction(10,20,30.9);
>}
>
>It just seems incredibly odd that it can process calls for functions it 
>knows nothing about, and may not actually exist, or exist but with a 
>totally different signature that will probably cause the program to 
>crash, but it can't do so for an actual function that is fully defined 
>20 lines further on in the file!


Well, it does that by making some huge assumptions as to what the
actual signature of the function is.  In the above case it's assuming
(I think):

  int anyfunction(int, int, double);

Which may well not match reality.  And which is why that usage is
depreciated.

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


#63027

FromKeith Thompson <kst-u@mib.org>
Date2015-06-06 13:52 -0700
Message-ID<87r3posgnp.fsf@kst-u.example.com>
In reply to#63022
Robert Wessel <robertwessel2@yahoo.com> writes:
> On Sat, 06 Jun 2015 19:09:56 +0100, Bartc <bc@freeuk.com> wrote:
[...]
>>But C compilers still seem happy to generate code for a non-existent 
>>function that they've not had sight of at all; gcc compiles this with no 
>>problem:
>>
>>int main(void) {
>>      anyfunction(10,20,30.9);
>>}
>>
>>It just seems incredibly odd that it can process calls for functions it 
>>knows nothing about, and may not actually exist, or exist but with a 
>>totally different signature that will probably cause the program to 
>>crash, but it can't do so for an actual function that is fully defined 
>>20 lines further on in the file!
>
>
> Well, it does that by making some huge assumptions as to what the
> actual signature of the function is.  In the above case it's assuming
> (I think):
>
>   int anyfunction(int, int, double);
>
> Which may well not match reality.  And which is why that usage is
> depreciated.

gcc follows the old C90 rules by default, which assume a specific
declaration for a function called with no visible declaration, under the
"implicit int" rule.

The usage was not deprecated, it was removed completely from the
language.  As of C99, calling a function with no visible declaration is
a constraint violation, requiring a compile-time diagnostic.

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


#63033

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-06-06 20:57 -0400
Message-ID<ml04ri$af4$1@dont-email.me>
In reply to#63027
On 06/06/2015 04:52 PM, Keith Thompson wrote:
> Robert Wessel <robertwessel2@yahoo.com> writes:
>> On Sat, 06 Jun 2015 19:09:56 +0100, Bartc <bc@freeuk.com> wrote:
> [...]
>>> But C compilers still seem happy to generate code for a non-existent 
>>> function that they've not had sight of at all; gcc compiles this with no 
>>> problem:
>>>
>>> int main(void) {
>>>      anyfunction(10,20,30.9);
>>> }
>>>
>>> It just seems incredibly odd that it can process calls for functions it 
>>> knows nothing about, and may not actually exist, or exist but with a 
>>> totally different signature that will probably cause the program to 
>>> crash, but it can't do so for an actual function that is fully defined 
>>> 20 lines further on in the file!
>>
>>
>> Well, it does that by making some huge assumptions as to what the
>> actual signature of the function is.  In the above case it's assuming
>> (I think):
>>
>>   int anyfunction(int, int, double);
>>
>> Which may well not match reality.  And which is why that usage is
>> depreciated.
> 
> gcc follows the old C90 rules by default, which assume a specific
> declaration for a function called with no visible declaration, under the
> "implicit int" rule.
> 
> The usage was not deprecated, it was removed completely from the
> language.  As of C99, calling a function with no visible declaration is
> a constraint violation, requiring a compile-time diagnostic.

True, but the return type of the function was only one of the five
assumptions  that a C90 compiler would have made about such a function,
and the other four  are still mandated if the declaration leaves them
unspecified. As of C2011, the language still allows a declaration that
specifies neither the number nor the types of the arguments.
-- 
James Kuyper

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


#63159

FromStephen Sprunk <stephen@sprunk.org>
Date2015-06-10 14:33 -0500
Message-ID<mla3bt$hs6$1@dont-email.me>
In reply to#63021
On 06-Jun-15 13:09, Bartc wrote:
> On 06/06/2015 17:11, Stephen Sprunk wrote:
>> On 05-Jun-15 12:22, Bartc wrote:
>>> That seems to be still the case, in that functions need to be
>>> declared before use (or at least, will cause problems if they're
>>> not).
>> 
>> That's because you need to know the argument and return types to 
>> properly generate the code to call the function.
> 
> That can't have been the actual reason for decades. It's unlikely
> that final code will be generated for a function before the rest of
> the file has been scanned.

Probably not these days, but the way C is defined, a compiler _could_
work line by line and conform, even if none of them actually still do
(or ever did) so.  That may seem silly, but it is what it is.

> But C compilers still seem happy to generate code for a non-existent 
> function that they've not had sight of at all; gcc compiles this with
> no problem:
> 
> int main(void) {
>      anyfunction(10,20,30.9);
> }

That's because there was a specific rule in the Standard on what to do
when code calls a function that hasn't been declared yet.

That was eventually recognized as a Bad Idea(tm) and removed in later
versions, but some compilers still do it anyway, or default to an older
version of C where it was still allowed.  Presumably, they wouldn't do
that unless it were necessary to avoid breaking old code.

C still allows function declarations with unspecified arguments, even
though that has also been known to be Bad Idea(tm) for just as long.

S

-- 
Stephen Sprunk         "God does not play dice."  --Albert Einstein
CCIE #3723         "God is an inveterate gambler, and He throws the
K5SSS        dice at every possible opportunity." --Stephen Hawking

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


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

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


csiph-web