Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #62931 > unrolled thread
| Started by | fl <rxjwg98@gmail.com> |
|---|---|
| First post | 2015-06-01 16:48 -0700 |
| Last post | 2015-06-05 10:56 -0700 |
| Articles | 20 on this page of 41 — 15 participants |
Back to article view | Back to comp.lang.c
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 →
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-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]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2015-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]
| From | Joe Pfeiffer <pfeiffer@cs.nmsu.edu> |
|---|---|
| Date | 2015-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]
| From | gwowen <gwowen@gmail.com> |
|---|---|
| Date | 2015-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]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-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]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2015-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]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2015-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]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-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]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2015-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]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-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]
| From | gwowen <gwowen@gmail.com> |
|---|---|
| Date | 2015-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]
| From | Stephen Sprunk <stephen@sprunk.org> |
|---|---|
| Date | 2015-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]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-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]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2015-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-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]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-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]
| From | Stephen Sprunk <stephen@sprunk.org> |
|---|---|
| Date | 2015-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