Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"Why does most C/C++ developer prefers char *c instead of char* c? Pin"

150 views
Skip to first unread message

Lynn McGuire

unread,
May 29, 2018, 7:12:57 PM5/29/18
to
"Why does most C/C++ developer prefers char *c instead of char* c?"
https://www.codeproject.com/Lounge.aspx?msg=5523356#xx5523356xx

I prefer "char * c".

Lynn

Melzzzzz

unread,
May 29, 2018, 7:25:03 PM5/29/18
to
char* c;
but
char *c,*d;
>
> Lynn


--
press any key to continue or any other to quit...

Chris M. Thomasson

unread,
May 29, 2018, 7:40:20 PM5/29/18
to
For me _personally_, I prefer the star to be closer to its type.

char const* const g = "Hello";

g is a const pointer, to a const char when read right to left.

Richard

unread,
May 29, 2018, 7:48:11 PM5/29/18
to
[Please do not mail me a copy of your followup]

Lynn McGuire <lynnmc...@gmail.com> spake the secret code
<pekmpb$3uj$1...@dont-email.me> thusly:

>"Why does most C/C++ developer prefers char *c instead of char* c?"
> https://www.codeproject.com/Lounge.aspx?msg=5523356#xx5523356xx

Without reading the link first, my answer is....

Because that's the way it was shown to me in K&R "C Programming
Language", 1st ed.

Where I work, they like 'char* c'. They pay me to make code for them,
so I write it the way they want.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Chris M. Thomasson

unread,
May 29, 2018, 7:49:32 PM5/29/18
to
On 5/29/2018 4:48 PM, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> Lynn McGuire <lynnmc...@gmail.com> spake the secret code
> <pekmpb$3uj$1...@dont-email.me> thusly:
>
>> "Why does most C/C++ developer prefers char *c instead of char* c?"
>> https://www.codeproject.com/Lounge.aspx?msg=5523356#xx5523356xx
>
> Without reading the link first, my answer is....
>
> Because that's the way it was shown to me in K&R "C Programming
> Language", 1st ed.
>
> Where I work, they like 'char* c'. They pay me to make code for them,
> so I write it the way they want.
>

No problem with that! :^D

Barry Schwarz

unread,
May 29, 2018, 11:10:40 PM5/29/18
to
On Tue, 29 May 2018 18:12:39 -0500, Lynn McGuire
<lynnmc...@gmail.com> wrote:

>"Why does most C/C++ developer prefers char *c instead of char* c?"
> https://www.codeproject.com/Lounge.aspx?msg=5523356#xx5523356xx

In my case because
char* c, d;
is visually misleading. d has type char, not char*. Using
char *c, d;
makes it clear, to me.

--
Remove del for email

James Kuyper

unread,
May 29, 2018, 11:36:04 PM5/29/18
to
For me, it's because it reflects the C grammar. I don't mean that it's
required by the grammar. I mean that the grammar specifies that a
declaration consists of a series of declaration specifiers followed by a
list of init-declarators (6.7p1). In this declaration, the declaration
specifiers consist entirely of the type specifier "char", while *c is
the sole pointer declarator. Putting a space between the declaration
specifiers and the init-declarators (a space NOT required by the
grammar) helps remind me of that distinction.

Let me give a bigger example, where I use a newline for the same
purpose. In the declaration

static int const _Alignas(double)
array[32]={[1]=1, [2]=1, [4]=1, [8]=1, [16]=1},
* restrict pointer=array;

The first line of that declaration contains all of the declaration
specifiers. The second line contains the first init-declarator, and the
third line contains the second init-declarator. All of the specifiers
apply to both init-declarators, whereas nothing specified for the first
init-declarator carries over to the second init-declarator, which is why
it's important, in general, to keep the distinction between specifiers
and declarators clear. However, if you never declare more than one
identifier in a given declaration, you don't need to worry about that
distinction.

Alf P. Steinbach

unread,
May 30, 2018, 1:27:52 AM5/30/18
to
template< class T > using Type_ = T;
Type_<char*> a, b;

or

template< class T > using Ptr_ = T*;
Ptr_<char> a, b;


Going down to the fundamental type builders, as in the last example,
supports using prefix `const` everywhere.

Almost like a sane programming language.

Cheers!,

- Alf

David Brown

unread,
May 30, 2018, 2:58:58 AM5/30/18
to
To me, they are /both/ visually misleading (though the second one is a
little less bad), and I much prefer to write:

char * c;
char * d;

Since I don't usually define a variable until I have an initial value,
my identifiers are mostly more descriptive, and there may well be a
comment, I very rarely see any reason to squeeze more than one
identifier in the same declaration.

Jorgen Grahn

unread,
May 30, 2018, 4:51:42 AM5/30/18
to
The question is flawed; C programmers and C++ programmers have
different conventions. You see more people saying 'char* c' in
C++ (although it's not a universal difference).

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

bart...@gmail.com

unread,
May 30, 2018, 5:38:34 AM5/30/18
to
[Attempting to post to C++ group only]
It's C type syntax, which has different characteristics depending on whether you're specifying a single nameless type, or declaring a list of N typed names.

So you have to make the best of bad job.

When declaring only a type (as in cast, or a nameless parameter), I would write "char*".

If declaring only a list of names but N=1, these days I might write "char* c" taking advantage that in this case, I can keep the type specifier in one group (but that doesn't work when declaring one array as in "char c[]" as the type is split around the name).

If declaring several such names, then I would probably write "char *c, *d" as otherwise "char* c, d" looks confusing: it resembles a saner language where you write "<typespec> c,d" with the same type applied to each name.

I would very rarely mix types in a declaration, so I wouldn't write "char *c, d" and intend that only one is a pointer.

And finally, if generating C code by software, I seem to remember using "char *" in each case, where the "*" looks rather lonely. But there, I only ever declare one name at a time so it probably doesn't matter.

--
bart

Juha Nieminen

unread,
May 30, 2018, 5:41:22 AM5/30/18
to
C++ inherits a lot of bad decisions from C, and I think that the
rather convoluted syntax for pointers is one of them. Pointers,
and their syntax, is one of the hardest things for a beginner
programmer to learn, regardless of whether we are talking about
C or C++. (Heck, it took me years to fully remember all the
intricacies, even though I regularly coded in C and C++ as
a hobby.)

It's easy to think that the asterisk is tied to the type,
even though it's not. Thus it's easy to get confused by
declarations like: char* a, b;

Of course if you have learned to always attach the asterisk to the
type name, it's a habit that's hard to get rid of, even if you wanted
to. Thus you often resort to inconsistent compromises, such as writing:

char* a;
char *b, *c; // Would look weird as "char* b, *c;"

I know because I do that often, even though I try to avoid it.

Of course even if you try to learn to attach the asterisk to the name,
you then get dilemmas like:

std::vector<char*> v;

Now the asterisk looks like part of the type name, almost by necessity.
I suppose you could use some slightly weird spacing like:

std::vector<char *>v;

but that's even more awful.

Attaching the asterisk to the name actually makes a lot more sense when
we are talking about things like function and array pointers, ie:

int (*funcPtr)(int);
int (*tablePtr)[12];

Here it would be weird to try to attach the asterisk, somehow, to the
type name. Especially since the type name isn't a pointer (the "type
name" in this case is int, not int*.)

Incidentally, in Objective-C method declarations have the type of a
parameter specified in parentheses, and a very common convention is to
attach the asterisk to the variable name regardless. In other words,
rather than write a method as:

- (void) methodName: (int*) intPtr;

it's often written by convention (eg. by Apple) as:

- (void) methodName: (int *)intPtr;

bart...@gmail.com

unread,
May 30, 2018, 6:20:18 AM5/30/18
to
On Wednesday, 30 May 2018 10:41:22 UTC+1, Juha Nieminen wrote:

> C++ inherits a lot of bad decisions from C, and I think that the
> rather convoluted syntax for pointers is one of them.

> It's easy to think that the asterisk is tied to the type,
> even though it's not. Thus it's easy to get confused by
> declarations like: char* a, b;

I think it would be best to always think of the asterisk (it's harder with [] for arrays) as part of the type.

This would work well for parameters (only one type per name), and casts (only one type with no name).

For other name declarations, you can use a convention of only declaring one name per type. Or for several names all of the same type, it's possible to wrap the type in a typedef. Alternatively, using this gcc extension, you can do this:

typeof(char*) p,q,r;

Each of p, q and r has type char*. This extension also allows you to make an array specifier part of the type:

typeof(char[10]) a,b,c;

It even works for functions:

typeof(int(int,int)) F {}

although people might expect a mode traditional declaration here. Functions are usually declared one at a time.

--
bart

Ian Collins

unread,
May 30, 2018, 6:36:27 AM5/30/18
to
On 30/05/18 18:58, David Brown wrote:
> On 30/05/18 05:10, Barry Schwarz wrote:
>> On Tue, 29 May 2018 18:12:39 -0500, Lynn McGuire
>> <lynnmc...@gmail.com> wrote:
>>
>>> "Why does most C/C++ developer prefers char *c instead of char* c?"
>>> https://www.codeproject.com/Lounge.aspx?msg=5523356#xx5523356xx
>>
>> In my case because
>> char* c, d;
>> is visually misleading. d has type char, not char*. Using
>> char *c, d;
>> makes it clear, to me.
>>
>
> To me, they are /both/ visually misleading (though the second one is a
> little less bad), and I much prefer to write:
>
> char * c;

That's a multiplication ! :)

--
Ian.

Scott Lurndal

unread,
May 30, 2018, 9:35:41 AM5/30/18
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>On 30.05.2018 05:10, Barry Schwarz wrote:
>> On Tue, 29 May 2018 18:12:39 -0500, Lynn McGuire
>> <lynnmc...@gmail.com> wrote:
>>
>>> "Why does most C/C++ developer prefers char *c instead of char* c?"
>>> https://www.codeproject.com/Lounge.aspx?msg=5523356#xx5523356xx
>>
>> In my case because
>> char* c, d;
>> is visually misleading. d has type char, not char*. Using
>> char *c, d;
>> makes it clear, to me.
>
> template< class T > using Type_ = T;
> Type_<char*> a, b;
>
>or
>
> template< class T > using Ptr_ = T*;
> Ptr_<char> a, b;
>

Good grief. What a waste of bytes.

char *p
char* p
#define ASTERISK *
char ASTERISK p

who cares?

Mr Flibble

unread,
May 31, 2018, 3:20:06 PM5/31/18
to
There is an even simpler (and better) solution: DON'T DECLARE MULTIPLE
VARIABLES ON THE SAME LINE.

/Flibble

--
"Suppose it’s all true, and you walk up to the pearly gates, and are
confronted by God," Bryne asked on his show The Meaning of Life. "What
will Stephen Fry say to him, her, or it?"
"I’d say, bone cancer in children? What’s that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery
that is not our fault. It’s not right, it’s utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a
world that is so full of injustice and pain. That’s what I would say."

bart...@gmail.com

unread,
May 31, 2018, 5:30:49 PM5/31/18
to
On Thursday, 31 May 2018 20:20:06 UTC+1, Mr Flibble wrote:

> There is an even simpler (and better) solution: DON'T DECLARE MULTIPLE
> VARIABLES ON THE SAME LINE.

That's not a solution, it's a workaround. And comes with a disadvantage; suppose that T includes any pointer, array, or function pointer modifiers, then instead of writing:

T x, y, z;

which tells you that these variables are likely related, and they have a common type which is automatically kept in sync, you have to write:

T x;
T y;
T z;

Then that relationship is lost, and it will need more maintenance to ensure they stay the same type.

So declaring several names with the same type spec is useful.

The original C syntax however allows you to declare several names together but with *different* types (and they can be wildly different), which is not useful and is bad practice.

--
bart

David Brown

unread,
May 31, 2018, 5:49:41 PM5/31/18
to
(Please get a real news client, or fix your line endings if you have to
use Google's broken interface. It makes it a pain for others to sort
out your messed up line breaks.)


On 31/05/18 23:30, bart...@gmail.com wrote:
> On Thursday, 31 May 2018 20:20:06 UTC+1, Mr Flibble wrote:
>
>> There is an even simpler (and better) solution: DON'T DECLARE
>> MULTIPLE VARIABLES ON THE SAME LINE.
>
> That's not a solution, it's a workaround.

It is a solution to the problem "how should I declare several pointer
variables in a way that won't be confusing?".

> And comes with a
> disadvantage; suppose that T includes any pointer, array, or function
> pointer modifiers, then instead of writing:
>
> T x, y, z;
>
> which tells you that these variables are likely related, and they
> have a common type which is automatically kept in sync, you have to
> write:
>
> T x;
> T y;
> T z;
>
> Then that relationship is lost, and it will need more maintenance to
> ensure they stay the same type.

That might, occasionally, be a relevant point. I can't speak for Mr.
Flibble, of course, but I would be okay with "T x, y, z;" in such simple
cases. But I am /not/ okay with "char* c, d;" or "char *c, d;" - it is
far too easy to misread these.

More commonly, however, you have longer type names (including
qualifiers), initialisers, descriptive variable names, comments, etc.,
which mean putting multiple object definitions on one line becomes a mess.


>
> So declaring several names with the same type spec is useful.

/Occasionally/ useful.

>
> The original C syntax however allows you to declare several names
> together but with *different* types (and they can be wildly
> different), which is not useful and is bad practice.
>

Agreed. And for me, that rule includes cases like the sample one here
with a "char" and a "char*".

Lynn McGuire

unread,
May 31, 2018, 6:55:21 PM5/31/18
to
+1,000,000

Lynn

Öö Tiib

unread,
Jun 1, 2018, 2:28:38 AM6/1/18
to
On Friday, 1 June 2018 00:30:49 UTC+3, bart...@gmail.com wrote:
> On Thursday, 31 May 2018 20:20:06 UTC+1, Mr Flibble wrote:
>
> > There is an even simpler (and better) solution: DON'T DECLARE MULTIPLE
> > VARIABLES ON THE SAME LINE.
>
> That's not a solution, it's a workaround. And comes with a disadvantage; suppose that T includes any pointer, array, or function pointer modifiers, then instead of writing:
>
> T x, y, z;

That is supposing code of seventies. Then it was that function calls
were too expensive so program consisted of only few long functions.
Language rules did not let to group related data into structs and all
local variables had to be declared at function start. There it was
too early to initialize any. Giving 4-letter name to something was too
lot of bytes and also pointless since most variables were reused in
different roles during function call.
Only few rocket scientists had enough storage for comments so most
code was write-only.

It may be that in your self-developed programming language there are
still those issues and problems. But why should others care about
issues of half of century ago? When to look at actual source code of
software that is written by team then we do not see that pattern
anywhere.
In actual C++ code we often see even function parameter declarations
(when there are several) to be split each to different line, nothing
to talk of local variables.

bart...@gmail.com

unread,
Jun 1, 2018, 5:35:51 AM6/1/18
to
On Thursday, 31 May 2018 22:49:41 UTC+1, David Brown wrote:
> (Please get a real news client, or fix your line endings if you have to
> use Google's broken interface. It makes it a pain for others to sort
> out your messed up line breaks.)

(I don't know if it's mine that's broken. My posts look fine via googlgroups. And also (since for some reason I get notified on it) on whatever app is used on my Android phone). Is it that hard for a newsreader to ensure that too-long lines are wrapped properly for display?)

--
bartc

Ian Collins

unread,
Jun 1, 2018, 5:50:51 AM6/1/18
to
On 01/06/18 09:30, bart...@gmail.com wrote:
> On Thursday, 31 May 2018 20:20:06 UTC+1, Mr Flibble wrote:
>
>> There is an even simpler (and better) solution: DON'T DECLARE MULTIPLE
>> VARIABLES ON THE SAME LINE.
>
> That's not a solution, it's a workaround.

It is also a very common coding standard rule.

> And comes with a disadvantage; suppose that T includes any pointer, array, or function pointer modifiers, then instead of writing:
>
> T x, y, z;
>
> which tells you that these variables are likely related, and they have a common type which is automatically kept in sync, you have to write:
>
> T x;
> T y;
> T z;
>
> Then that relationship is lost, and it will need more maintenance to ensure they stay the same type.

In that case, put them is a struct/class and manage them as a group.

--
Ian.

bart...@gmail.com

unread,
Jun 1, 2018, 6:20:30 AM6/1/18
to
Are you serious? And even if I did that, surely I would have the same problem of ensuring they are the same type, unless they shared the same type specifier?

Here's an example of related identifiers (also an example of single-letter identfiers):

int64 evaliandexpr(void) {
int64 x, y;

x = evaleqexpr();
while (nextlx.symbol == iandsym) {
lexm();
x &= evaleqexpr();
}
return x;
}

Tell me what possible improvement in readability there can be by putting x and y into a managed struct (whatever that actually means). Or with this same code by declaring x and y on different lines (to address another poster's concern). Or by using longer identifiers for x and y (to address yet another).

Aren't some people also in favour of having a short function bodies as possible? These suggestions would tend to make them longer.


--
bart

David Brown

unread,
Jun 1, 2018, 6:27:44 AM6/1/18
to
It is your end that is broken - Google Group's interface does not follow
the standard Usenet formatting rules. Of course your GG posts look fine
in GG - and perhaps other Google apps - but they are not ideal for
standard newsreaders.

Of course, none of this is your fault or unique to you - it is a general
problem with Google Groups, and nothing personal.


I can't be sure about newsreaders other than Thunderbird, as that's what
I use, but your posts display okay. Thunderbird sees your long lines
from GG (each paragraph is a line) and wraps them to fit the window.
(Other newsreaders may not wrap well for reading either.)

But when I reply to your posts, your long lines get quoted as long lines
- quoting should not change the format. When quoted, however, they are
no longer wrapped by newsreaders. Thunderbird has a "re-wrap" command
to help that fixes the line breaks most of the time. But it also
"fixes" code by considering the adjacent lines as a paragraph, putting
them all together into one long line, then breaking that line at 72
character line widths as though it were text.

All this means that most people can usually read your posts okay, but
some might find it a pain if their newsreaders don't wrap. And replying
to your posts is extra effort and inconvenience. It is not uncommon in
some newsgroups for people to simply filter out every post made from
Google Groups as being too much effort to bother with.


If you can, I strongly recommend getting a real newsreader client, and a
real newsserver. People can, and do, argue endlessly about the best
software - I hope to avoid that here. I'll simply say that Thunderbird
is a fine choice for many people - it is free, works on Windows, Macs,
and *nix, and has the features most users need.
news.eternal-september.org is a fine choice of newsserver - again, it is
free. GG is handy if you want to search in archives or look
occasionally at an odd group, but a proper newsreader makes life easier
for the groups you follow.

And when you do use GG, you can enter line breaks manually.

bart...@gmail.com

unread,
Jun 1, 2018, 6:31:29 AM6/1/18
to
On Friday, 1 June 2018 07:28:38 UTC+1, Öö Tiib wrote:
> On Friday, 1 June 2018 00:30:49 UTC+3, bart...@gmail.com wrote:
> > On Thursday, 31 May 2018 20:20:06 UTC+1, Mr Flibble wrote:
> >
> > > There is an even simpler (and better) solution: DON'T DECLARE MULTIPLE
> > > VARIABLES ON THE SAME LINE.
> >
> > That's not a solution, it's a workaround. And comes with a disadvantage; suppose that T includes any pointer, array, or function pointer modifiers, then instead of writing:
> >
> > T x, y, z;
>
> That is supposing code of seventies. Then it was that function calls
> were too expensive so program consisted of only few long functions.
> Language rules did not let to group related data into structs and all
> local variables had to be declared at function start. There it was
> too early to initialize any. Giving 4-letter name to something was too
> lot of bytes and also pointless since most variables were reused in
> different roles during function call.
> Only few rocket scientists had enough storage for comments so most
> code was write-only.
>
> It may be that in your self-developed programming language there are
> still those issues and problems.

That would be an interesting limitation of a programming language to insist on two or more variables declared together!

While I haven't recently come across a language where you can only have one-letter identifiers.

> But why should others care about
> issues of half of century ago? When to look at actual source code of
> software that is written by team then we do not see that pattern
> anywhere.

Tell me, how would such a team rewrite fragments of code like this:

void swap(int* x, int* y){...}
#define MAX(x, y) ...
A[i][j][k]; // inside a 3-nested loop indexed by i,j,k

Or the evaliandexpr() routine in my last post.

Single letter names are used extensively in mathematics, and for similar reasons they also work for local variables of functions in programming languages.


--
bart

Ian Collins

unread,
Jun 1, 2018, 7:11:18 AM6/1/18
to
On 01/06/18 22:20, bart...@gmail.com wrote:
> On Friday, 1 June 2018 10:50:51 UTC+1, Ian Collins wrote:
>> On 01/06/18 09:30, bart...@gmail.com wrote:
>>> On Thursday, 31 May 2018 20:20:06 UTC+1, Mr Flibble wrote:
>>>
>>>> There is an even simpler (and better) solution: DON'T DECLARE MULTIPLE
>>>> VARIABLES ON THE SAME LINE.
>>>
>>> That's not a solution, it's a workaround.
>>
>> It is also a very common coding standard rule.
>>
>>> And comes with a disadvantage; suppose that T includes any pointer, array, or function pointer modifiers, then instead of writing:
>>>
>>> T x, y, z;
>>>
>>> which tells you that these variables are likely related, and they have a common type which is automatically kept in sync, you have to write:
>>>
>>> T x;
>>> T y;
>>> T z;
>> >
>>> Then that relationship is lost, and it will need more maintenance to ensure they stay the same type.
>>
>> In that case, put them is a struct/class and manage them as a group.
>
> Are you serious? And even if I did that, surely I would have the same problem of ensuring they are the same type, unless they shared the same type specifier?
>
> Here's an example of related identifiers (also an example of single-letter identfiers):

It's also an example of an unused variable...

> int64 evaliandexpr(void) {
> int64 x, y;
>
> x = evaleqexpr();
> while (nextlx.symbol == iandsym) {
> lexm();
> x &= evaleqexpr();
> }
> return x;
> }

--
Ian.

David Brown

unread,
Jun 1, 2018, 7:13:33 AM6/1/18
to
int64 evaliandexpr(void) {
int64_t x = evaleqexpr();
while (nextlx.symbol == iandsym) {
lexm();
x &= evaleqexpr();
}
return x;
}

I'm happy with short identifier names in small contexts. I am not
impressed with short identifier names in a wider context (like "lexm"),
nor by jammedupidentifier styles - use camelCase or under_scores to
split up words.

And I can't see any advantage of putting the definition of "x" before
its initialisation. It is not going to make a difference to generated
code here, with a simple type like int64_t, but for more complex C++
types separate definitions then assignments can be a different thing and
lower efficiency than initialisation.

Certainly I see no advantage in putting the definition of "y" on the
same line as that of "x", when it is not used at all. Defining your
objects when you need them, and initialising them at the same time,
helps avoid the confusion and possible inefficiency of extra objects
like "y" in this example.

Scott Lurndal

unread,
Jun 1, 2018, 9:11:56 AM6/1/18
to
=?UTF-8?B?w5bDtiBUaWli?= <oot...@hot.ee> writes:
>On Friday, 1 June 2018 00:30:49 UTC+3, bart...@gmail.com wrote:
>> On Thursday, 31 May 2018 20:20:06 UTC+1, Mr Flibble wrote:
>>
>> > There is an even simpler (and better) solution: DON'T DECLARE MULTIPLE
>> > VARIABLES ON THE SAME LINE.
>>
>> That's not a solution, it's a workaround. And comes with a disadvantage; suppose that T includes any pointer, array, or function pointer modifiers, then instead of writing:
>>
>> T x, y, z;
>
>That is supposing code of seventies. Then it was that function calls
>were too expensive so program consisted of only few long functions.

What gives you that impression? Function calls were not expensive
in the 70's. Or in the 60's. Just a simple branch, generally saving
the return address in the first word of the target function (e.g. PDP-8)
or on a stack (Burroughs/IBM mainframes).

>Language rules did not let to group related data into structs and all

COBOL anyone?

>local variables had to be declared at function start. There it was
>too early to initialize any. Giving 4-letter name to something was too
>lot of bytes and also pointless since most variables were reused in
>different roles during function call.
>Only few rocket scientists had enough storage for comments so most
>code was write-only.

Complete nonsense.

bart...@gmail.com

unread,
Jun 1, 2018, 10:38:29 AM6/1/18
to
On Friday, 1 June 2018 12:13:33 UTC+1, David Brown wrote:
> On 01/06/18 12:20, bart...@gmail.com wrote:

> > Here's an example of related identifiers (also an example of single-letter identfiers):
> >
> > int64 evaliandexpr(void) {
> > int64 x, y;
> >
> > x = evaleqexpr();
> > while (nextlx.symbol == iandsym) {
> > lexm();
> > x &= evaleqexpr();
> > }
> > return x;
> > }
> >
> > Tell me what possible improvement in readability there can be by
> > putting x and y into a managed struct

> int64 evaliandexpr(void) {
> int64_t x = evaleqexpr();
> while (nextlx.symbol == iandsym) {
> lexm();
> x &= evaleqexpr();
> }
> return x;
> }
>
> I'm happy with short identifier names in small contexts. I am not
> impressed with short identifier names in a wider context (like "lexm"),

'lexm' is a local function in this module, and it is clearly a function because it is followed by (). I don't see the problem.

> nor by jammedupidentifier styles - use camelCase or under_scores to
> split up words.

I mix and match styles just to break things up. Some names within a project will have underscores, some sets will have a common prefix, others a common suffix, and some both (see below). But all names in the same related set will use the same scheme

> And I can't see any advantage of putting the definition of "x" before
> its initialisation.

I have a problem with your version because the important initialisation of x is separated from the rest of the code.

I like to separate code that just provides information, like a declaration, from code that actualy does something, like the assigment. The algorithm here is to assign the first lhs term to x then loop for any rhs terms. Your version breaks that up.

It also involves the type of x (and y; see below) more than I would like. If one day I decide to change their type, then I would need to change the block of code that expresses the algorithm. As I have it, I could copy and paste that block unchanged into a place where x and y are different types. Or even where they have no types at all (eg. to in a dynamic language where x and y don't even need declaring).


> Certainly I see no advantage in putting the definition of "y" on the
> same line as that of "x", when it is not used at all. Defining your
> objects when you need them, and initialising them at the same time,
> helps avoid the confusion and possible inefficiency of extra objects
> like "y" in this example.

This function is one of set of a dozen, all with the same interface, all named 'evalOPexpr', all declaring 'int64 x,y'. Most will use y, in one or two it was dispensed with (such as the one I chose to post), but I yet make use of it in the future.

These functions evaluate the operands of a binary operator and it is natural to call those operands x and y.

Daniel

unread,
Jun 1, 2018, 10:41:09 AM6/1/18
to
On Friday, June 1, 2018 at 9:11:56 AM UTC-4, Scott Lurndal wrote:
> >
> >That is supposing code of seventies. Then it was that function calls
> >were too expensive so program consisted of only few long functions.
>
> What gives you that impression?

Possibly IBM FORTRAN documentation :-)

I recall from the late 70's that the IBM FORTRAN documentation contained a description of a function as something you wouldn't use very often, but could be used if you had some common code.

Daniel

Scott Lurndal

unread,
Jun 1, 2018, 11:15:30 AM6/1/18
to
Fortran (on IBM) was, perhaps atypical. COBOL and ALGOL used
functions/subroutines very heavily (e.g. the COBOL PERFORM verb)
as did more proprietary languages like Burroughs BPL or HP SPL.

Mr Flibble

unread,
Jun 1, 2018, 1:29:37 PM6/1/18
to
On 01/06/2018 15:38, bart...@gmail.com wrote:
> On Friday, 1 June 2018 12:13:33 UTC+1, David Brown wrote:
>> And I can't see any advantage of putting the definition of "x" before
>> its initialisation.
>
> I have a problem with your version because the important initialisation of x is separated from the rest of the code.
>
> I like to separate code that just provides information, like a declaration, from code that actualy does something, like the assigment.

But this is C++ not C and in C++ there is an important distinction between
initialization and assignment. There are likely many C++ coding standards
that prohibit defining variables without initializing them in the definition.

Ian Collins

unread,
Jun 1, 2018, 3:36:20 PM6/1/18
to
On 02/06/18 02:38, bart...@gmail.com wrote:

Please sort your line wrap...

> It also involves the type of x (and y; see below) more than I would
> like. If one day I decide to change their type, then I would need to
> change the block of code that expresses the algorithm. As I have it,
> I could copy and paste that block unchanged into a place where x and
> y are different types. Or even where they have no types at all (eg.
> to in a dynamic language where x and y don't even need declaring).

So just use auto; then the type is whatever evaleqexpr() returns. The
type is irrelevant to the algorithm, so why make a fuss about it or even
name it?

>> Certainly I see no advantage in putting the definition of "y" on
>> the same line as that of "x", when it is not used at all. Defining
>> your objects when you need them, and initialising them at the same
>> time, helps avoid the confusion and possible inefficiency of extra
>> objects like "y" in this example.
>
> This function is one of set of a dozen, all with the same interface,
> all named 'evalOPexpr', all declaring 'int64 x,y'. Most will use y,
> in one or two it was dispensed with (such as the one I chose to
> post), but I yet make use of it in the future.

With clang and g++, this will generate an unused variable warning with
all but the most basic compilers options.

--
Ian.

Bart

unread,
Jun 1, 2018, 4:28:05 PM6/1/18
to
On 01/06/2018 20:36, Ian Collins wrote:
> On 02/06/18 02:38, bart...@gmail.com wrote:
>
> Please sort your line wrap...
>
>> It also involves the type of x (and y; see below) more than I would
>> like. If one day I decide to change their type, then I would need to
>> change the block of code that expresses the algorithm. As I have it,
>> I could copy and paste that block unchanged into a place where x and
>> y are different types. Or even where they have no types at all (eg.
>> to in a dynamic language where x and y don't even need declaring).
>
> So just use auto; then the type is whatever evaleqexpr() returns.

No, the type needs to be int64 in this case (in another version, I might
decide to use int32 or whatever).

It might happen that evaleqexpr() always returns that type too, but
confidence in that is not quite the 100% it is when being explicit about
the type.

> type is irrelevant to the algorithm, so why make a fuss about it or even
> name it?

It's not that irrelevant. But specifying it (although it might be better
in one place as a typedef), it's clear that this code [part of #if
<expr> processing for a CPP] has chosen to use signed 64-bit arithmetic.

>> This function is one of set of a dozen, all with the same interface,
>> all named 'evalOPexpr', all declaring 'int64 x,y'. Most will use y,
>> in one or two it was dispensed with (such as the one I chose to
>> post), but I yet make use of it in the future.
>
> With clang and g++, this will generate an unused variable warning with
> all but the most basic compilers options.

That's fine when you've finished your program and wrapped it up.

It would be a nuisance during development when you've declared a bunch
of variables but haven't got round to making use of them, or haven't
decided which are staying. Or some of them are there for possible debugging.

If, for example, I need to print out those two operands, then it will be
easier if the rhs one is assigned to y. But wait - I had to get rid of
it to remove that annoying warning.

--
bartc

Ian Collins

unread,
Jun 1, 2018, 5:38:43 PM6/1/18
to
On 02/06/18 08:27, Bart wrote:
> On 01/06/2018 20:36, Ian Collins wrote:
>> On 02/06/18 02:38, bart...@gmail.com wrote:
>>
>> Please sort your line wrap...
>>
>>> It also involves the type of x (and y; see below) more than I would
>>> like. If one day I decide to change their type, then I would need to
>>> change the block of code that expresses the algorithm. As I have it,
>>> I could copy and paste that block unchanged into a place where x and
>>> y are different types. Or even where they have no types at all (eg.
>>> to in a dynamic language where x and y don't even need declaring).
>>
>> So just use auto; then the type is whatever evaleqexpr() returns.
>
> No, the type needs to be int64 in this case (in another version, I might
> decide to use int32 or whatever).

So another version would squeeze a quart into a pint pot?

> It might happen that evaleqexpr() always returns that type too, but
> confidence in that is not quite the 100% it is when being explicit about
> the type.

Why would the type be anything other than the return of evaleqexpr()?

>> type is irrelevant to the algorithm, so why make a fuss about it or even
>> name it?
>
> It's not that irrelevant. But specifying it (although it might be better
> in one place as a typedef), it's clear that this code [part of #if
> <expr> processing for a CPP] has chosen to use signed 64-bit arithmetic.
>
>>> This function is one of set of a dozen, all with the same interface,
>>> all named 'evalOPexpr', all declaring 'int64 x,y'. Most will use y,
>>> in one or two it was dispensed with (such as the one I chose to
>>> post), but I yet make use of it in the future.
>>
>> With clang and g++, this will generate an unused variable warning with
>> all but the most basic compilers options.
>
> That's fine when you've finished your program and wrapped it up.
>
> It would be a nuisance during development when you've declared a bunch
> of variables but haven't got round to making use of them, or haven't
> decided which are staying. Or some of them are there for possible debugging.

That is terrible practice. You should only introduce variables when and
were you need them. Anything is is chaos.

> If, for example, I need to print out those two operands, then it will be
> easier if the rhs one is assigned to y. But wait - I had to get rid of
> it to remove that annoying warning.

So you prefer to print uninitialised gobbledygook?

--
Ian.

Öö Tiib

unread,
Jun 1, 2018, 7:20:14 PM6/1/18
to
One of the first programming languages I used was FORTRAN and it
made exactly the impression that I expressed. It was good since
it was easy to form clear vision what is wrong with it. Also it
is easy to recognize those wrong things (whenever pushed) to
this day. But back then one brave soul at 1982 wrote that:
"Besides, the determined Real Programmer can write FORTRAN
programs in any language." Perhaps you have read that essay.


Öö Tiib

unread,
Jun 1, 2018, 7:35:28 PM6/1/18
to
Huh? Why you swap ints? Even MISRA (<- most backward minded crowd),
does not allow to type "int" in their code standards.

Bart

unread,
Jun 1, 2018, 7:47:28 PM6/1/18
to
On 01/06/2018 22:38, Ian Collins wrote:
> On 02/06/18 08:27, Bart wrote:

>> It might happen that evaleqexpr() always returns that type too, but
>> confidence in that is not quite the 100% it is when being explicit about
>> the type.
>
> Why would the type be anything other than the return of evaleqexpr()?

The type of what? There could be three different ones.

In this function, you want to emphasise that x and y (when both are
used) have the same type. You want to do that without having to analyse
different parts of function. You might also want to know what that type
is without having to hunt for the called functions.

If somebody wants to take my function and port it to an unknown language
(unknown to us), then they would likely find it easiest working from the
code that /I/ write than the C or C++ versions other people are suggesting.

> That is terrible practice.  You should only introduce variables when and
> were you need them.  Anything is is chaos.
Have you done any real programming where you build an application
incrementally, or have to copy and paste from one part to another, or
have to comment out code, or delete code that that will be replaced, but
you still have the declarations, or...

In other words, just normal development. Because it doesn't sound like it!

Do you only ever submit complete, debugged working programs to a
compiler? Do you only ever declare a variable when all the references to
that variable in the code are complete? Would you ever write a skeleton
function like this:

int fn(int a, int b, int c){
puts("fn not ready");
return 0;
}

If so, how do you cope with with warnings about a, b and c not being used?

--
bartc

Ian Collins

unread,
Jun 1, 2018, 8:06:51 PM6/1/18
to
On 02/06/18 11:47, Bart wrote:
> On 01/06/2018 22:38, Ian Collins wrote:
>> On 02/06/18 08:27, Bart wrote:
>
>>> It might happen that evaleqexpr() always returns that type too, but
>>> confidence in that is not quite the 100% it is when being explicit about
>>> the type.
>>
>> Why would the type be anything other than the return of evaleqexpr()?
>
> The type of what? There could be three different ones.
>
> In this function, you want to emphasise that x and y (when both are
> used) have the same type. You want to do that without having to analyse
> different parts of function. You might also want to know what that type
> is without having to hunt for the called functions.

I would have thought the emphasis is on the algorithm, not the types.

> If somebody wants to take my function and port it to an unknown language
> (unknown to us), then they would likely find it easiest working from the
> code that /I/ write than the C or C++ versions other people are suggesting.

How many people do that? That someone might want to port to language B
a pretty daft justification for avoiding the idioms of language A.

>> That is terrible practice.  You should only introduce variables when and
>> were you need them.  Anything is is chaos.

> Have you done any real programming where you build an application
> incrementally, or have to copy and paste from one part to another, or
> have to comment out code, or delete code that that will be replaced, but
> you still have the declarations, or...

Nope. My code is written incrementally, one passing test at a time.
There is no code that isn't introduced to make a test pass.

> In other words, just normal development. Because it doesn't sound like it!

Normal from days gone by, maybe.

> Do you only ever submit complete, debugged working programs to a
> compiler?

No, because I have to verify that it won't pass a new test before the
code to pass the test is written.

> Do you only ever declare a variable when all the references to
> that variable in the code are complete?

A variable is introduced once it can be correctly initialised.

> Would you ever write a skeleton
> function like this:
>
> int fn(int a, int b, int c){
> puts("fn not ready");
> return 0;
> }
>
> If so, how do you cope with with warnings about a, b and c not being used?

By not naming them.

--
Ian

Ian Collins

unread,
Jun 1, 2018, 8:14:38 PM6/1/18
to
On 02/06/18 11:47, Bart wrote:
> On 01/06/2018 22:38, Ian Collins wrote:
>
>> That is terrible practice.  You should only introduce variables when and
>> were you need them.  Anything is is chaos.

> Have you done any real programming where you build an application
> incrementally, or have to copy and paste from one part to another, or
> have to comment out code, or delete code that that will be replaced, but
> you still have the declarations, or...

What you describe there is analogous to a surgeon leaving dead tissue
and instruments in a patient after surgery!

--
Ian.

Jorgen Grahn

unread,
Jun 2, 2018, 3:53:52 AM6/2/18
to
On Fri, 2018-06-01, Scott Lurndal wrote:
> =?UTF-8?B?w5bDtiBUaWli?= <oot...@hot.ee> writes:
>>On Friday, 1 June 2018 00:30:49 UTC+3, bart...@gmail.com wrote:
>>> On Thursday, 31 May 2018 20:20:06 UTC+1, Mr Flibble wrote:
>>>
>>> > There is an even simpler (and better) solution: DON'T DECLARE MULTIPLE
>>> > VARIABLES ON THE SAME LINE.
>>>
>>> That's not a solution, it's a workaround. And comes with a
>>> disadvantage; suppose that T includes any pointer, array, or
>>> function pointer modifiers, then instead of writing:
>>>
>>> T x, y, z;
>>
>>That is supposing code of seventies. Then it was that function calls
>>were too expensive so program consisted of only few long functions.
>
> What gives you that impression?

Whatever caused it, I had that impression until 1995 or so. And
reading others' code, it seems many still do: it's not uncommon to
find long functions which could easily could have been improved by
having helper functions factored out.

But perhaps the latter has more to do with people seeing functions as
necessarily big, important and visible in external interfaces.

> Function calls were not expensive
> in the 70's. Or in the 60's. Just a simple branch, generally saving
> the return address in the first word of the target function (e.g. PDP-8)
> or on a stack (Burroughs/IBM mainframes).

The branch instruction is a small part of the cost.

[snip]

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

David Brown

unread,
Jun 2, 2018, 6:42:01 AM6/2/18
to
On 01/06/18 16:38, bart...@gmail.com wrote:
> On Friday, 1 June 2018 12:13:33 UTC+1, David Brown wrote:
>> On 01/06/18 12:20, bart...@gmail.com wrote:
>
>>> Here's an example of related identifiers (also an example of
>>> single-letter identfiers):
>>>
>>> int64 evaliandexpr(void) { int64 x, y;
>>>
>>> x = evaleqexpr(); while (nextlx.symbol == iandsym) { lexm(); x &=
>>> evaleqexpr(); } return x; }
>>>
>>> Tell me what possible improvement in readability there can be by
>>> putting x and y into a managed struct
>
>> int64 evaliandexpr(void) { int64_t x = evaleqexpr(); while
>> (nextlx.symbol == iandsym) { lexm(); x &= evaleqexpr(); } return
>> x; }
>>
>> I'm happy with short identifier names in small contexts. I am not
>> impressed with short identifier names in a wider context (like
>> "lexm"),
>
> 'lexm' is a local function in this module, and it is clearly a
> function because it is followed by (). I don't see the problem.

It is clearly a function, yes. I'd be suspicious of such a short-named
function - even when it is local to a module (I hope you've remembered
"static" or an anonymous namespace). If it is local, commonly used, and
the name is obvious within the context of the program, then "lexm" might
be fine.

>
>> nor by jammedupidentifier styles - use camelCase or under_scores
>> to split up words.
>
> I mix and match styles just to break things up. Some names within a
> project will have underscores, some sets will have a common prefix,
> others a common suffix, and some both (see below). But all names in
> the same related set will use the same scheme
>

Using different styles for different purposes is fine, and can help
improve legibility. Some people prefer underscores, some prefer
camel-case - I'm not going to argue for one or the other. But jammed-up
identifiers without a break between the words, are always hard to read.
That makes them bad style in almost all circumstances.

>> And I can't see any advantage of putting the definition of "x"
>> before its initialisation.
>
> I have a problem with your version because the important
> initialisation of x is separated from the rest of the code.

No, it is not. The initialisation is right there with the rest of the code.

In your version, there is no initialisation of x - but its definition is
separated.

>
> I like to separate code that just provides information, like a
> declaration, from code that actualy does something, like the
> assigment.

Then you picked the wrong language. In C++, definitions (rather than
just declarations) /do/ something (even if, for simple types and a good
compiler, that "logical something" may involve no object code). And
"int64_t x" inside a function is a definition, not just a declaration.

> The algorithm here is to assign the first lhs term to x
> then loop for any rhs terms. Your version breaks that up.

No, it does not. It has the same actions in the same place. The only
difference is that "x" is not declared earlier.

>
> It also involves the type of x (and y; see below) more than I would
> like. If one day I decide to change their type, then I would need to
> change the block of code that expresses the algorithm.

No, you would not. You would only need to change it in one place at the
start of the block. And it would make no sense to change the type of
"x" unless you were also changing the type of evaleqexpr() - you need to
make multiple changes anyway.

And if you had several variables to deal with here, you would use a
"using" (modern C++) or "typedef" (older C++ and C) to name the type,
thus you would only have to change it at one point. (Your evaleqexpr()
function would use that same typedef'ed type.)

You can also use modern C++ style and use "auto" instead of the type for x.

> As I have it,
> I could copy and paste that block unchanged into a place where x and
> y are different types. Or even where they have no types at all (eg.
> to in a dynamic language where x and y don't even need declaring).
>
>
>> Certainly I see no advantage in putting the definition of "y" on
>> the same line as that of "x", when it is not used at all. Defining
>> your objects when you need them, and initialising them at the same
>> time, helps avoid the confusion and possible inefficiency of extra
>> objects like "y" in this example.
>
> This function is one of set of a dozen, all with the same interface,
> all named 'evalOPexpr', all declaring 'int64 x,y'. Most will use y,
> in one or two it was dispensed with (such as the one I chose to
> post), but I yet make use of it in the future.

If you define your variables when you need them, you don't need to
pre-define extra variables just to make copy-and-paste easier.

>
> These functions evaluate the operands of a binary operator and it is
> natural to call those operands x and y.
>

I am quite happy with the operands being called "x" and "y" - that seems
a good choice of names here.

David Brown

unread,
Jun 2, 2018, 6:54:17 AM6/2/18
to
On 01/06/18 22:27, Bart wrote:
> On 01/06/2018 20:36, Ian Collins wrote:
>> On 02/06/18 02:38, bart...@gmail.com wrote:
>>

>>> This function is one of set of a dozen, all with the same interface,
>>> all named 'evalOPexpr', all declaring 'int64 x,y'. Most will use y,
>>> in one or two it was dispensed with (such as the one I chose to
>>> post), but I yet make use of it in the future.
>>
>> With clang and g++, this will generate an unused variable warning with
>> all but the most basic compilers options.
>
> That's fine when you've finished your program and wrapped it up.
>

Absolutely not. Enable warnings from the moment you start with your
first empty C file and its first build. You want to deal with problems
(or potential problems) as quickly as possible, not let them build up
until you think you've finished the code and then discover all the issues!

> It would be a nuisance during development when you've declared a bunch
> of variables but haven't got round to making use of them, or haven't
> decided which are staying. Or some of them are there for possible
> debugging.

If you don't define them until you need them, this is not a problem. If
they are useful for debugging, then there will be no compiler warnings
about them - if the compiler is warning about them (that they are
unused, or assigned to but unused), then they are useless for debugging.

David Brown

unread,
Jun 2, 2018, 7:04:16 AM6/2/18
to
I want the warnings. Then I am not going to forget that the function is
missing!

Early in development, I have warnings as warnings, and accept that there
are while coding. Parts of the development may even be done as first
adding the stubs that lead to warnings, and then going through fixing
the warnings. (A good IDE makes this convenient and practical.) Then I
use "-Werror" to turn all warnings into errors.

David Brown

unread,
Jun 2, 2018, 7:10:14 AM6/2/18
to
On 02/06/18 02:06, Ian Collins wrote:
> On 02/06/18 11:47, Bart wrote:

>> Do you only ever declare a variable when all the references to
>> that variable in the code are complete?
>
> A variable is introduced once it can be correctly initialised.
>
>> Would you ever write a skeleton
>> function like this:
>>
>>     int fn(int a, int b, int c){
>>       puts("fn not ready");
>>       return 0;
>>     }
>>
>> If so, how do you cope with with warnings about a, b and c not being
>> used?
>
> By not naming them.
>

I hate when people declare functions without naming the parameters. If
you don't have a use for something, then it should not be there. And if
you have a use for it, it needs a name. (A rare exception being
"operator++(int)".)

If I have reason to leave a parameter unused, and don't want a warning
(for example, to give consistent interfaces to a number of functions),
then I use "__attribute__((unused))" or cast the variable to void.

Bart

unread,
Jun 2, 2018, 7:12:40 AM6/2/18
to
On 02/06/2018 01:06, Ian Collins wrote:
> On 02/06/18 11:47, Bart wrote:

>> Have you done any real programming where you build an application
>> incrementally, or have to copy and paste from one part to another, or
>> have to comment out code, or delete code that that will be replaced, but
>> you still have the declarations, or...
>
> Nope.  My code is written incrementally, one passing test at a time.
> There is no code that isn't introduced to make a test pass.

Then I envy you your clear and simple specifications!

My current project is a new compiler X for a static language M' written
in static language M. Parts of X will be taken from an old compiler for
M written in dynamic language Q, and parts from a more recent compile
written in M but which compiles C source code.

So there are lots of imported bits which can't immediately be used
because they need dynamic->static conversion, or which have been
converted but are intended to compile C (with a different set of AST
nodes and different intermediate language). Or they can't be used
because the new compiler works differently from the other two (a project
at a time rather than a module at a time).

It's not practical to convert everything all at once. There will be
loads of stuff commented out or half converted or which I know will be
wrong, but it just needs to be get past the compiler to do a test that
might be unrelated to that half-done function.

So yes it's chaotic. But so are lots of things (like writing a
screenplay adapted from something else; there will be lots of rewriting
and refining and even starting again).

Your strategy sounds very worthy but is the equivalent of calling in a
team of management consultants and project managers to help me build a
garden fence.

>> In other words, just normal development. Because it doesn't sound like
>> it!
>
> Normal from days gone by, maybe.

>> Do you only ever submit complete, debugged working programs to a
>> compiler?
>
> No, because I have to verify that it won't pass a new test before the
> code to pass the test is written.

I couldn't program like that.

As for testing, my project X from above is now being tried on a sizeable
input Y'. Y' is a 20Kloc interpreter.

It partly 'works' in that Y' can be converted from source code to a
binary executable (an achievement given the things that can and have
gone wrong), and the next step is running Y' on its own input Z.

Testing then is seeing whether X compiling Y' interpreting Z gives the
same results as original working Y interpreting Z.

So if something doesn't work, there is source code for three separate
projects to consider. When it gets more advanced, Z can be the compiler
that compiles X, then it gets more interesting as I can then test second
and third generation X' and X''. After that X's source code will be
tweaked from M to M' and X will compile itself directly.

Oh, and X is intended to compile code at up to 500Kloc per second.
(Although I'm some way short of that at the minute; X needs twice as
many passes as my C compiler. Still, X should be able to compile itself
at the rate of several generations per second, even UNOPTIMISED. How
many will C++ do?).

Now, this is chaotic but it's fun. With your formal, sterile approach to
coding, I'd be looking for a 6' length of rope inside a week.

--
bartc

Ian Collins

unread,
Jun 2, 2018, 4:17:25 PM6/2/18
to
Which is all well and good in C, C++ has unnamed parameters for that case.

--
Ian.

Bart

unread,
Jun 2, 2018, 4:27:07 PM6/2/18
to
What happens when you eventually decide to use that parameter, but
forget to name it and it happens to shadow a more global variable with
the same name?

Let me guess: unit tests will pick that up.

--
bartc


Ian Collins

unread,
Jun 2, 2018, 4:32:36 PM6/2/18
to
So why ask?

--
Ian.

Ian Collins

unread,
Jun 2, 2018, 4:45:50 PM6/2/18
to
On 02/06/18 23:12, Bart wrote:
> On 02/06/2018 01:06, Ian Collins wrote:
>> On 02/06/18 11:47, Bart wrote:
>
>>> Have you done any real programming where you build an application
>>> incrementally, or have to copy and paste from one part to another, or
>>> have to comment out code, or delete code that that will be replaced, but
>>> you still have the declarations, or...
>>
>> Nope.  My code is written incrementally, one passing test at a time.
>> There is no code that isn't introduced to make a test pass.
>
> Then I envy you your clear and simple specifications!

The clarity and completeness of the specification is orthogonal to the
process. Ours are generally along the lines of "as an operator, I need
to do blah...". Doing Blah will usually involve changes to multiple
modules withing both the controls and UI code bases.

<snip>

> Your strategy sounds very worthy but is the equivalent of calling in a
> team of management consultants and project managers to help me build a
> garden fence.

The strategy enables us to modify and extend existing code knowing we
haven't disrupted its original functionality and enables future
maintainers to modify the new code with the same assurances. Chaos can
quickly turn to catastrophe when there are over one hundred people
working on the same code base...

>>> In other words, just normal development. Because it doesn't sound like
>>> it!
>>
>> Normal from days gone by, maybe.
>
>>> Do you only ever submit complete, debugged working programs to a
>>> compiler?
>>
>> No, because I have to verify that it won't pass a new test before the
>> code to pass the test is written.
>
> I couldn't program like that.

You have the luxury of working solo and deadline free on your own code!

--
Ian.

guinne...@gmail.com

unread,
Jun 2, 2018, 7:48:06 PM6/2/18
to
On Friday, 1 June 2018 10:35:51 UTC+1, bart...@gmail.com wrote:
> On Thursday, 31 May 2018 22:49:41 UTC+1, David Brown wrote:
> > (Please get a real news client, or fix your line endings if you have to
> > use Google's broken interface. It makes it a pain for others to sort
> > out your messed up line breaks.)
>
> (I don't know if it's mine that's broken. My posts look fine via googlgroups. And also (since for some reason I get notified on it) on whatever app is used on my Android phone). Is it that hard for a newsreader to ensure that too-long lines are wrapped properly for display?)
>
> --
> bartc

And yet you can't be arsed to format your lines to less than 80 characters.

It's really not that hard.

But, then again, you're Bart and find even the simplest tasks hard.

David Brown

unread,
Jun 3, 2018, 11:28:19 AM6/3/18
to
And C++ also lets you name the parameters.

Unnamed parameters make sense for purely overload purposes, including
types with only a single object (like nullptr_t, nothrow_t, etc.).
There would usually be no reason to use the parameter of such types.

But other than that, I /want/ parameters to have names - even if I don't
use them.

David Brown

unread,
Jun 3, 2018, 11:30:44 AM6/3/18
to
Maybe you'd spot the problem using compiler warnings, before even having
to run the tests?

Scott Lurndal

unread,
Jun 4, 2018, 10:51:46 AM6/4/18
to
Aside from any cache related costs (not a problem in the 70's), what
additional costs are there in your concept of 70's functions?

Richard

unread,
Jun 4, 2018, 12:57:55 PM6/4/18
to
[Please do not mail me a copy of your followup]

bart...@gmail.com spake the secret code
<3c80ec4e-c59b-46d5...@googlegroups.com> thusly:

>On Thursday, 31 May 2018 20:20:06 UTC+1, Mr Flibble wrote:
>
>> There is an even simpler (and better) solution: DON'T DECLARE MULTIPLE
>> VARIABLES ON THE SAME LINE.
>
>That's not a solution, it's a workaround. And comes with a disadvantage;
>suppose that T includes any pointer, array, or function pointer
>modifiers, then instead of writing:
>
> T x, y, z;
>
>which tells you that these variables are likely related, and they have a
>common type which is automatically kept in sync, you have to write:
>
> T x;
> T y;
> T z;
>
>Then that relationship is lost, and it will need more maintenance to
>ensure they stay the same type.

This is really just a missing abstraction. If you want a 3D point,
make a type for it. It's zero-overhead in C++ and allows you to
express the idea directly in code.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Bart

unread,
Jun 4, 2018, 1:05:37 PM6/4/18
to
On 04/06/2018 17:57, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> bart...@gmail.com spake the secret code
> <3c80ec4e-c59b-46d5...@googlegroups.com> thusly:
>
>> On Thursday, 31 May 2018 20:20:06 UTC+1, Mr Flibble wrote:
>>
>>> There is an even simpler (and better) solution: DON'T DECLARE MULTIPLE
>>> VARIABLES ON THE SAME LINE.
>>
>> That's not a solution, it's a workaround. And comes with a disadvantage;
>> suppose that T includes any pointer, array, or function pointer
>> modifiers, then instead of writing:
>>
>> T x, y, z;
>>
>> which tells you that these variables are likely related, and they have a
>> common type which is automatically kept in sync, you have to write:
>>
>> T x;
>> T y;
>> T z;
>>
>> Then that relationship is lost, and it will need more maintenance to
>> ensure they stay the same type.
>
> This is really just a missing abstraction. If you want a 3D point,
> make a type for it.

The 3 values might form a vector with those three components, but
usually they won't or you have other reasons for independent access to
the variables.

But even suppose you did encapsulate them into a type; the problem
doesn't go away: do you declare them inside that type with one T and 3
names, or three Ts?

--
bartc

Richard

unread,
Jun 4, 2018, 1:12:22 PM6/4/18
to
[Please do not mail me a copy of your followup]

Bart <b...@freeuk.com> spake the secret code
<mjeRC.286699$Z64.1...@fx36.am4> thusly:
It's irrelevant at that point because the abstraction makes it clear
that they all belong together.

Vir Campestris

unread,
Jun 4, 2018, 3:57:37 PM6/4/18
to
On 04/06/2018 15:51, Scott Lurndal wrote:
> Aside from any cache related costs (not a problem in the 70's), what
> additional costs are there in your concept of 70's functions?

I assure you cache was an issue in the '70s. OK, it was only single
level, and we had no branch predictors - but the cache on a 2900 was
good enough that a dual processor would run some workloads more than
twice as fast as a single CPU machine.

Andy

David Brown

unread,
Jun 4, 2018, 4:00:13 PM6/4/18
to
The cost of a function call - compared to inlining the code - will
depend a lot on the function, the cpu, the compiler, and how much of the
code the compiler can see. But typical additional costs include moving
data into the right registers for the calling convention (for cpus with
few registers, this is little cost - also for cpus which have register
renaming these can often be swallowed early in the pipeline. But for
single issue cpus with lots of registers, it is costly). Data that is
in "volatile" registers needs to be saved or re-created around the
function call. The compiler loses information about what data may or
may not be accessed, and thus has to flush write data from registers and
reload read data after the call. The compiler loses the opportunity to
merge the code for scheduling benefits, constant propagation, common
subexpression optimisations, etc.

Function calls can be very cheap, but they can also be significant cost.

Scott Lurndal

unread,
Jun 4, 2018, 4:46:40 PM6/4/18
to
A rare machine indeed, with both cache and SMP. The B2900 (Burroughs)
had neither.

Scott Lurndal

unread,
Jun 4, 2018, 4:49:15 PM6/4/18
to
The original point was that there was no movement or commandment to
avoid function calls in the 70's due to the perceived expense. Nor
were there pipelines or, in general, software-visible caches in the
70's.

Functions were not at all uncommon in Fortran, COBOL or the
many algol and algol-like languages in that era, even BASIC
heavily used functions (GOSUB).

Lynn McGuire

unread,
Jun 4, 2018, 5:13:35 PM6/4/18
to
On 6/1/2018 8:11 AM, Scott Lurndal wrote:
...
>> local variables had to be declared at function start. There it was
>> too early to initialize any. Giving 4-letter name to something was too
>> lot of bytes and also pointless since most variables were reused in
>> different roles during function call.
>> Only few rocket scientists had enough storage for comments so most
>> code was write-only.
>
> Complete nonsense.

We used the UCS Univac 1108 for software development until 1978 when we
got a Prime 450. We could barely afford to keep the code online on
those old drum drives, much less the comments. So, no comments in our
source code until 1978. And those comments sucked.

I would love for our code from back then to have four letter variable
names. We generally have:
T = temperature
P = pressure
V = vapor
L = liquid
B = hydrocarbon liquid
I = integer iterator

Lynn


David Brown

unread,
Jun 5, 2018, 3:35:50 AM6/5/18
to
I had very limited computing experience in the 70's, certainly not of
big computers.

>
> Functions were not at all uncommon in Fortran, COBOL or the
> many algol and algol-like languages in that era, even BASIC
> heavily used functions (GOSUB).
>

Oh, certainly functions are heavily used, and have been since the
invention of the callable subroutine. Just because they can, in some
circumstances, be costly does not mean that they are not worth the cost.
(And they are not always slower than inlining - the benefits of cache,
pre-fetches, branch caches, etc., combined with hardware scheduling can
mean that even having lots of small functions can be faster in some cases.)

Jorgen Grahn

unread,
Jun 5, 2018, 4:18:17 AM6/5/18
to
I was thinking about saving and restoring registers, and inability to
optimize across function boundaries.

But to be honest I thought more of the 1980s and the Motorola 68000.
I never meant to claim to know anything about what programmers did in
the 1970s.

Scott Lurndal

unread,
Jun 5, 2018, 10:01:12 AM6/5/18
to
Jorgen Grahn <grahn...@snipabacken.se> writes:
>On Mon, 2018-06-04, Scott Lurndal wrote:
>> Jorgen Grahn <grahn...@snipabacken.se> writes:
>>>On Fri, 2018-06-01, Scott Lurndal wrote:
>>
>>>> Function calls were not expensive
>>>> in the 70's. Or in the 60's. Just a simple branch, generally saving
>>>> the return address in the first word of the target function (e.g. PDP-8)
>>>> or on a stack (Burroughs/IBM mainframes).
>>>
>>>The branch instruction is a small part of the cost.
>>
>> Aside from any cache related costs (not a problem in the 70's), what
>> additional costs are there in your concept of 70's functions?
>
>I was thinking about saving and restoring registers, and inability to
>optimize across function boundaries.

Many of the machines of that era were memory-to-memory architectures
with only an accumulator and a couple of index registers or auto-increment
locations in low memory (e.g. pdp-8,
burroughs mainframes) or stack based (burroughs large systems, HP-3000).

In many cases, function weren't re-entrant (e.g. the PDP-8 again, because
the return address is stored in the first word of the function, or the
Burroughs systems were system call parameters were in the code stream
following the system call instruction).

Vir Campestris

unread,
Jun 5, 2018, 4:41:34 PM6/5/18
to
Ah, I meant an ICL 2900. I didn't know about the Burroughs one.

Andy
0 new messages