Coding style survey

  • Thread starter Papadopoulos Giannis
  • Start date
J

Jim Lambert

Mark A. Odell said:
And here comes junior programmer dude... "I'll just add another pointer
type here..."


"Hey, I got a 'type' instead of a 'pointer to type', what gives?"

True, JPD could do that but he could just as easily do it with the * being
next to the p instead of the type. :)
 
B

Bruno Desthuilliers

Nick said:
It's a matter of personal preference.

If someone doesn't like the way you do it, let them
write a "pretty printer" to reformat it.
Why re-writing something that exists and is free ?-)

Bruno
 
B

Bruno Desthuilliers

Papadopoulos said:
Which do you think is best?

1.
a) type* p;
b) type *p;

b if you write C code (in C++, the idiom is a)
2.
a) return (var);
b) return(var);
c) return var;

c, of course.
3.
a) return (ptr->var);
b) return(ptr->var);
c) return ptr->var;

c, of course.
4.
a) return (foo(ptr->var));
b) return(foo(ptr->var));
c) return foo(ptr->var);

c, of course.
5.
a) a = (b+c);
b) a=(b+c);
c) a = b+c;
d) a=b+c;

None. The One Right Way(tm) is
a = b + c;

6.
(snip)

d)
type foo(type arg1, type arg2, ...)
{
declarations;

code;

return;
}

(snip)

But all this is pretty
1/ a matter of taste
2/ more or less language specific

Bruno
 
M

Malcolm

Richard Bos said:
Not at all. The function containing the return statement could be a
function which prepares the data for foo().
So there are exceptions. As a rule of thumb, however, if a function calls
another function that returns a value, then the caller is the appropriate
level to process that value - not simply to return it to a higher level.
If you need to prepare data for foo() then that would be an indication that
foo() is badly written. Just an indication, mind you, there might be some
cases where the problems of formatting input neatly are so deep-rooted that
foo() needs a setup function..
My recent MiniBasic program was over 3000 lines. I don't think there is a
single case of returning a sub-function's value directly in all that code.
 
R

Richard Bos

Malcolm said:
So there are exceptions. As a rule of thumb, however, if a function calls
another function that returns a value, then the caller is the appropriate
level to process that value - not simply to return it to a higher level.

Any reasons for that statement?
If you need to prepare data for foo() then that would be an indication that
foo() is badly written.

Nonsense. Look at the example I gave: it could easily be an indication
that foo() can work on any data, and the calling function uses it to
work on specific data.

Richard
 
S

Severian

So there are exceptions. As a rule of thumb, however, if a function calls
another function that returns a value, then the caller is the appropriate
level to process that value - not simply to return it to a higher level.
If you need to prepare data for foo() then that would be an indication that
foo() is badly written. Just an indication, mind you, there might be some
cases where the problems of formatting input neatly are so deep-rooted that
foo() needs a setup function.

Bullshit. There are many useful and valid reasons to return foo().
My recent MiniBasic program was over 3000 lines. I don't think there is a
single case of returning a sub-function's value directly in all that code.

My current application is over 1,000,000 lines. And there are quite a
few functions that return foo(), for various reasons (some elegant,
some for readability, and some just old and gnarly). So there!

- Sev
 
C

CBFalconer

Richard said:
.... snip ...

Any reasons for that statement?


Nonsense. Look at the example I gave: it could easily be an
indication that foo() can work on any data, and the calling
function uses it to work on specific data.

Example:

/* function with side effects returning 0/1 for success/fail */
int foo(/* params */)
{
...
if (conditions) return 0;
else if (failurecondition) return 1;
else {
....
return foo(/* revised params */);
}
}

Yes, it can easily have recursion removed.
 
A

Alan Balmer

If you need to prepare data for foo() then that would be an indication that
foo() is badly written.

No, it simply means that the data you have is not appropriate for
foo() without preparation. foo() may be common processing for data in
more than one form, or foo() may be a standard library function.
 
M

Malcolm

Richard Bos said:
Any reasons for that statement?
Sure. The basic idea of structured programming is that the program is
divided into a hierarchy of functions, becoming more general-purpose as you
move down the hierachy, more specific as you move up.
The other principle is that each function performs one closely-defined task,
and is a black box to the function that calls it.
This means that if we have a function bar() that calls foo(), and barb()
calls bar(), barb() shouldn't know that bar() is calling foo().
This means that barb() shouldn't know the intricacies of foo(). Any change
to foo() shouldn't imply a change in barb(), but only in bar() (where it is
unavoidable).
This does not absolutely preclude returning a result directly from foo() in
barb(), but it does mean that occasions for doing so will be rare, and can
be used as a marker for code that is likely to be poorly-designed, because
the function hierarchy isn't abstracting foo() from bar().

Let's give a concrete example.

void barb()
{
char *str;

str = bar();
if(!str)
out_of_memory_error();
}

char *bar()
{
return foo("duplicate this string\n");
}

char *foo(char *str)
{
char *answer = malloc(strlen(str)+1);
strcpy(answer, str);
return answer;
}

Now let's modify foo(). Let's say that we only handle strings of ten
characters or less. If passed more than ten, return 0.
Now you will notice that barb() is now broken, because it is reporting an
out-of-memory condition when in fact the error is "string too long". However
barb() doesn't call foo(), so a search for all instances of the identifier
foo() won't pick this up.
Of course in a short program we can easily correct the error, and in a long
program bar() should be correctly-documented (but how likely is the
programmer who wrote bar() to say "returns 0 on error" when he really meant
"returns 0 on out-of-memory"?).
By not handling the return value at the correct level you are spoiling the
structure of your program.
Nonsense. Look at the example I gave: it could easily be an indication
that foo() can work on any data, and the calling function uses it to
work on specific data.
It means that foo() is too general for the real caller to use. The function
cinterp(char *cfunction) which runs a c interpreter on arbitrary source is
completely general, but also not much use.
Now there can be good reasons for providing a very general function. For
instance you could impement sqrt() as return pow(x, 0.5). However see the
problem - sqrt() is a special case of exponentiation, and it can be
implemented a lot more efficiently. If you already have a working pow() nad
you don't care about run-time efficiency then go ahead. This is not an
untypical case. Take quad( ... four points ... ) axis_aligned_rectangle( ...
two points ...) could be implemented as a call to quad(), but again this
only makes sense in the special circumstances of having a working quad() and
no access to its display buffer.
Microsoft have provided a very customisable OpenFile() dialog. For programs
intended for distribution to end users it probably makes sense. However in a
testing and quick tools environment you generally want to write fname =
getopenfile(), rather than go to the help pages to see how to set up a
complex input structure. So arguably the function is badly-designed.
 
G

gabriel

Papadopoulos said:
1.
a) type* p;
b) type *p;
B

2.
a) return (var);
b) return(var);
c) return var;
B

3.
a) return (ptr->var);
b) return(ptr->var);
c) return ptr->var;
B

4.
a) return (foo(ptr->var));
b) return(foo(ptr->var));
c) return foo(ptr->var);
B

5.
a) a = (b+c);
b) a=(b+c);
c) a = b+c;
d) a=b+c;

None. I use "a = b + c;"
6.
a)
type foo(type arg1, type arg2, ...) {
declarations;
code;
return;
}
b)
type foo(type arg1, type arg2, ...) {
declarations;

code;

return;
}
c)
type foo(type arg1, type arg2, ...)
{
declarations;
code;
return;
}
d)
type foo(type arg1, type arg2, ...)
{
declarations;

code;

return;
}
e)
type foo(type arg1, type arg2, ...)
{
declarations;
code;
return;
}
f)
type foo(type arg1, type arg2, ...)
{
declarations;

code;

return;
}

B
 
G

gabriel

Papadopoulos said:
Which do you think is best?
[...]

LOL! I wrote my own reply, and the started to notice some of the other
replies... Jeez! Some people even pick fights over this without an
opponent!

Gotta loooove C programmers!
 
O

Old Wolf

I never use the comma operator since I have every variable on it's own line
so I don't have to worry about the "type* p, q" problem.

The comma in "type* p, q" is NOT an operator.
 
P

Paul Hsieh

Papadopoulos Giannis said:
Which do you think is best?
1.
a) type* p;
b) type *p;

Always the second. This is made clear in when you have multiple
declarers:

char *p, q, c, *x;

If the * were moved next to the type, you can see how this might be
confusing.
2, 3, 4.
a) return (var);
b) return(var);
c) return var;

c) is correct and requires fewer characters. Otherwise there is no
difference.
5.
a) a = (b+c);
b) a=(b+c);
c) a = b+c;
d) a=b+c;

I prefer a = b + c; which I guess is closest to choice c). You should
only use extra parenthesis where one is intending to be explicit about
the order of operations.
6. (spacing, and parentheses for functions ...)

I usually put an extra space between declarations and code, however I
don't add an extra one for the return (especially since a function
might return from any number of places from within the code.) So my
style would be closest to:

type foo(type arg1, type arg2, ...) {
declarations;

code;
return ...;
}
 
P

Paul Hsieh

Malcolm said:
c), return is not a function. Though you want to ask why you are returning
the return value from another function directly - this is unusual.

Its not unusual, and it might be a macro rather than a function.
 
E

E. Robert Tisdale

Paul said:
Always the second.
This is made clear in when you have multiple declarers:

char *p, q, c, *x;

This is considered very *poor* programming style
for a number of reasons:

1. you declare variables where constants may be required,
2. your variables are undefined and
3. your variables are undocumented.

const
char c = 'c'; // character constant
char q = '\0'; // character variable
const
char* const x = "some constant string";
const
char* p = &c; // reseatable pointer to a
// character constant

These *definitions* should be placed as close as possible
to the point where they are first used.
 
A

Arthur J. O'Dwyer

This is considered very *poor* programming style
for a number of reasons:

1. you declare variables where constants may be required,
2. your variables are undefined and
3. your variables are undocumented.

const
char c = 'c'; // character constant

This was about the point where I realized that this must be
another of Trollsdale's joke posts. It's just so blatantly stupid!
[Looking back, I see I should have seen that his "1." was nonsensical,
but he's clever with words that way -- it slipped right by me. :) ]

Paul -- Indeed, the declaration style of intermixing pointers
and scalars in the same line of variable declarations is a Bad
Idea, precisely because it is so confusing and hard to read.
But I think you know this, and were merely giving a contrived
example.

Newbies who have little experience with Trollsdale's joke
posts -- I would hope it's obvious that the following lines of
code are *also* incredibly bad style.
Don't use C++ comments in C code that's supposed to be read
and used by real-world C compilers (which includes all code posted
to this newsgroup). Don't put 'const' on a separate line from
the rest of a declaration. Don't put random tabs before variable
names, unless it's with a very good reason. (Oh, and don't use
hard tabs in Usenet posts to begin with.) Also, don't use the
style of pointer declaration exhibited by Trollsdale's last line,
in which he puts the asterisk way over on the left, where it can
be hidden in the mass of 'const's and 'char's. Oh, and don't use
comments like "character variable" in your code, either.

char q = '\0'; // character variable
const
char* const x = "some constant string";
const
char* p = &c; // reseatable pointer to a
// character constant

These *definitions* should be placed as close as possible
to the point where they are first used.

This is good advice. (That doesn't mean you should assume that
Trollsdale will *always* include a nugget of good advice in each
of his joke posts, though -- quite often he doesn't. You're better
off ignoring his posts.)

HTH,
-Arthur
 
P

Paul Hsieh

Arthur J. O'Dwyer said:
This was about the point where I realized that this must be
another of Trollsdale's joke posts.

Oh, I just read the "From:" part of the message to know that.
[...] It's just so blatantly stupid!
[Looking back, I see I should have seen that his "1." was nonsensical,
but he's clever with words that way -- it slipped right by me. :) ]

Paul -- Indeed, the declaration style of intermixing pointers
and scalars in the same line of variable declarations is a Bad
Idea, precisely because it is so confusing and hard to read.
But I think you know this, and were merely giving a contrived
example.

I disagree, and I think this is at best a matter of opinion. Since
there is nothing controvertial about what the compiler does (except
the issue of the "*" being associated with the variable/type being
declared instead of the defining type) there is nothing specific that
it can be confused with so long as "*"'s are pushed to be adjacent to
the variable.

Also, its not contrived -- go download Bstrlib and see for yourself.
This is good advice.

Most good compilers already help you with this potential problem, and
this is not a practical/useful suggestion for a large struct or ADT.
Since initialization, is of arbitrary complexity, attempting to do so
solely within the declaration section is kind of futile in general.
 
J

Joona I Palaste

Why is mr. Tisdale hated so much??

Because he frequently gives bad advice to others. Not only that, but he
sometimes also edits others' posts to make them read what he wanted them
to read.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,139
Messages
2,570,806
Members
47,353
Latest member
TamiPutnam

Latest Threads

Top