By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,854 Members | 849 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,854 IT Pros & Developers. It's quick & easy.

Coding style survey

P: n/a
Which do you think is best?

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

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

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

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

5.
a) a = (b+c);
b) a=(b+c);
c) a = b+c;
d) 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;
}

Nov 14 '05 #1
Share this Question
Share on Google+
63 Replies


P: n/a
In article <bv***********@ulysses.noc.ntua.gr>,
Papadopoulos Giannis <ip******@inf.uth.gr> wrote:
Which do you think is best?

1.
a) type* p;
b) type *p;
It depends on the situation. What is the important object: The pointer
p, or the object pointed to *p ? Occasionally you will see things like

char* *p;

which means that p points to a char-pointer.
2.
a) return (var);
b) return(var);
c) return var;
c
3.
a) return (ptr->var);
b) return(ptr->var);
c) return ptr->var;
Same
4.
a) return (foo(ptr->var));
b) return(foo(ptr->var));
c) return foo(ptr->var);
Same, but it should be foo (ptr->var)
5.
a) a = (b+c);
b) a=(b+c);
c) a = b+c;
d) a=b+c;
None of the above. 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;
}


None of the above. (b) with an empty line before declarations.
Nov 14 '05 #2

P: n/a
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.

If the company you are working for has a standard for any of
these, comply with their standard. It has nothing to do
with the correctness of the code, but may have impact
on how the code will be maintained in the future.

Papadopoulos Giannis wrote:
Which do you think is best?

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

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

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

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

5.
a) a = (b+c);
b) a=(b+c);
c) a = b+c;
d) 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;
}


--
"It is impossible to make anything foolproof because fools are so
ingenious" - A. Bloch

Nov 14 '05 #3

P: n/a
Nick Landsberg wrote:
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.

If the company you are working for has a standard for any of
these, comply with their standard. It has nothing to do
with the correctness of the code, but may have impact
on how the code will be maintained in the future.


I know.. I have already my style (which is by the way a bit peculiar)..
I just wanted to know how other c programmers code (either experts or
novice)...

Nov 14 '05 #4

P: n/a

"Papadopoulos Giannis" <ip******@inf.uth.gr> wrote in message
Which do you think is best?

1.
a) type* p;
b) type *p;
a) is clearer, since p is a type*. However b) is traditional, because of C's
rules on building compound types. See function pointers for further details.
2.
a) return (var);
b) return(var);
c) return var;
c). return is not a function. 3.
a) return (ptr->var);
b) return(ptr->var);
c) return ptr->var;
c), return is not a function. 4.
a) return (foo(ptr->var));
b) return(foo(ptr->var));
c) return foo(ptr->var);
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. 5.
a) a = (b+c);
b) a=(b+c);
c) a = b+c;
d) a=b+c;
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;
}

c) or d). Curly braces should always be on a line of their own and should
always align with the closing curly brace. A space between declarations and
code is generally useful, but |I wouldn't insist on it.
Nov 14 '05 #5

P: n/a


Malcolm wrote:
"Papadopoulos Giannis" <ip******@inf.uth.gr> wrote in message
Which do you think is best?
{snip} <--- not curly braces :)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;
}


c) or d). Curly braces should always be on a line of their own and should
always align with the closing curly brace. A space between declarations and
code is generally useful, but |I wouldn't insist on it.

It's again only a matter of personal preference and has nothing
to do with the correctness of the code or C, the language.

Back in the stone age of computing I developed a {} style which
put the curly braces on the same line as the "if, for, while, etc."
statements so I could use *nix system utilities to check for
flow of control, e.g. g/[{}]/p in the editor. Of course, this
did not help all the time. It was just a crutch.

If you are in an organization which has certain edicts for
where braces go, and you don't like them, then write your
own "pretty printer" and "un-pretty printer" to go back
and forth from your preferred style to the organization's
style. (Said pretty printer is a pretty good exercise in
learning the c-language, too.) We've had "brace wars" in
C for longer than I care to remember.

--
"It is impossible to make anything foolproof because fools are so
ingenious" - A. Bloch

Nov 14 '05 #6

P: n/a
Papadopoulos Giannis wrote:
Which do you think is best?

1.
a) type* p;

2.
c) return var;

3.
c) return ptr->var;

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

5.
c) a = b + c;

6.
a)
type foo(type arg1, type arg2, ...) {
declarations;
code;
return arg1;
}

Style is a very subjective and personal consideration.
C and C++ programmers develop or adopt a style
in order to make their code easier for themselves
and other programmers to read, understand and maintain.
If you are developing your own style, there are no rules
except that you should try to be consistent.
Otherwise, you should try to adopt a style
with which other C and C++ programmers are comfortable,
familiar or that they will at least recognize.
Personally, I try to use the same punctuation rules
that are used for ordinary (mathematical) typesetting.
Here are my recommendations:

Terminators always follow immediately after an expression

x@ for all @ in {?, :, ,, ;}

and are followed by at least one white space.
Write

x? y: z

instead of

x ? y : z

or

x?y:z

and write

void f(int, int, int); void g(double);

instead of

void f(int,int,int);void g(double);

for example.

There is no space
between some binary operators and their operands

x@y for all @ in {::, ., ->, .*, ->*, *, /, %, &, ^, |}

but there is always a space
between other binary operators and their operands

x @ y for all @ in {+, -, <<, >>;, <, <=, >, >=, ==, !=,
&&, ||, =, *=, /=, %=, +=, -=, <<=, >>=, &=, |=, ^=}

except when expressions appear as subscripts.
Write

x + y

instead of

x+y
and

x*y

instead of

x * y

for example.
But you may wish to write

A[i+1][j-1]

instead of

A[i + 1][j - 1]

for example to subscript array A.
Most unary prefix operators never have any whitespace
between themselves and their operands

@x for all @ in {::, ++, --, ~, !, -, +, &, *}

but others do

@ x for all @ in {sizeof, new, delete, delete [], throw}

No unary postfix operators

x@ for all @ in {[], (), ++, --}

ever have any whitespace between themselves and their operands.

Use the normal typesetting rules for parentheses (),
square brackets [], angle brackets <> and curly brackets {}.
No space after (, [, < or { and no space before ), ], > or }.
Write

(x)

instead of

( x )

or

(x )

or

( x)

and write

[x]

instead of

[ x ]

or

[x ]

or

[ x]

for example.
There are, of course, exceptions
where extra white space helps to make your code more readable:

double A[2][3] = {{ 1, -1, 0},
{-10, 11, -21}};
Don't give identifiers cryptic, mangled names.
Use ordinary, meaningful words, conventional symbols
or abbreviations with annotations.
Write

double distance, velocity, acceleration, mass, Force;

Force = mass*acceleration;

or

double x; // distance
double v; // velocity
double a; // acceleration
double m; // mass
double F; // force

F = m*a;

for example.

Don't rely on defaults. Make declarations explicit.
Write

int i = 1;

instead of

i = 1;

to declare and initialize integer i and write

class X {
private:
// Representation
int I;
public:
// Constructors
// ...
};

instead of

class X {
// Representation
int I;
public:
// Constructors
// ...
};

to define the private data members of class X for example.
Use indentation to emphasize scope.
Everybody is comfortable with standard indentation:

void f()
{
// indent
}

But I indent curly brackets to the scope of the function body:

void f()
{
// indent
}

And I include the open curly bracket with the function heading:

void f() {
// indent
}

to save a line of code.

I always indent just two spaces at a time and
I place just one statement on each line so that
there is usually room for a comment at the end of each line
beginning in column 33 or 41.

Write

if (condition) {
// statements
}

instead of

if(condition) {
// statements
}

and

while (condition) {
// statements
}

instead of

while(condition) {
// statements
}

to distinguish flow control structures from function calls.

I use

// comment

for comments in C++ and I reserve

/*
a = b;
// comment
b = c;
*/

to comment out code which may include comments.
If you find yourself in an environment
that requires you to conform to style rules with which you are not
comfortable,
consider investing a little time and effort in a program like astyle

Artistic Style
http://astyle.sourceforge.net/

which changes the appearance of C or C++ programs
by inserting or deleting whitespace.

Write

constant == variable

instead of

variable == constant

when comparing a variable to a constant for equality
so that if you write

constant = variable

by mistake, the compiler will detect the error.

I always write

x < y

or

x <= y

instead of

y > x

or

y >= x

when comparing two values so that the expression is true
when the left hand side is to the left of the right hand side
on the real number line.

Nov 14 '05 #7

P: n/a
On Tue, 27 Jan 2004 00:15:20 +0200, Papadopoulos Giannis
<ip******@inf.uth.gr> wrote in comp.lang.c:
Which do you think is best?


What I think is that people who ask about "style" issues are asking
the wrong question.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #8

P: n/a
Malcolm wrote:

.... snip ...

c) or d). Curly braces should always be on a line of their own and
should always align with the closing curly brace. A space between
declarations and code is generally useful, but |I wouldn't insist
on it.


I would. And the only code oriented place I insist on a separate
line for an opening brace is immediately after a function header.
Otherwise it belongs on the end of a line. e.g. my style:

int function foo(int bar)
{
/* declarations */

/* code after a blank line, unless no declarations */
if (bar) {
/* barstuff. Indentation shows controlling clause */
}
} /* foo */ /* I insist on labelling the end of a function */

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #9

P: n/a
Papadopoulos Giannis <ip******@inf.uth.gr> wrote:
Which do you think is best?

1.
a) type* p;
b) type *p;
The latter. The former leads people to believe that

int* p1,p2;

declares two pointers to int, which it does not.
2.
a) return (var);
b) return(var);
c) return var;
The third, but this is purely a matter of taste - except that I think
the second option makes it look too much like a function call. IOW, I'd
write the third; wouldn't frown at the first; but would remark upon the
second.
3.
a) return (ptr->var);
b) return(ptr->var);
c) return ptr->var; 4.
a) return (foo(ptr->var));
b) return(foo(ptr->var));
c) return foo(ptr->var);
Ditto, and ditto.
5.
a) a = (b+c);
b) a=(b+c);
c) a = b+c;
d) a=b+c;
C or D, depending on context.
6.
a)
type foo(type arg1, type arg2, ...) {
declarations;
code;
return;
}
No. I'd use this layout, with the opening brace at the end of the line,
for a block inside a function (for, if, etc.), but not for the function
block itself.
c)
type foo(type arg1, type arg2, ...)
{
declarations;
code;
return;
}
d)
type foo(type arg1, type arg2, ...)
{
declarations;

code;

return;
}
One of these; which I choose depends on the size of the function, but
usually D.
e)
type foo(type arg1, type arg2, ...)
{
declarations;
code;
return;
}


*Grk* No. Never. It's weird.

Richard
Nov 14 '05 #10

P: n/a
"Malcolm" <ma*****@55bank.freeserve.co.uk> wrote:
"Papadopoulos Giannis" <ip******@inf.uth.gr> wrote in message
4.
a) return (foo(ptr->var));
b) return(foo(ptr->var));
c) return foo(ptr->var);

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.


Not at all. The function containing the return statement could be a
function which prepares the data for foo().
For example, take a deque, implemented as a doubly linked list. The DLL,
of course, has a function called dll_delete(). The deque has two
functions, deq_l_delete() and deq_r_delete(). deq_l_delete(q) finds the
leftmost element of q, then passes it to dll_delete(); deq_r_delete(q)
does the same at the other end. The last statement of deq_l_delete()
could be

return dll_delete(leftmost);

Richard
Nov 14 '05 #11

P: n/a
CBFalconer <cb********@yahoo.com> wrote in message news:<40***************@yahoo.com>...
int function foo(int bar)
{
...
if (bar) {
/* barstuff. Indentation shows controlling clause */
}
} ...
Bravo! Glad to see someone adhering to the TRUE STYLE.
From an earlier discussion I thought comp.lang.c'ers thought it was passe.
Which do you think is best?
1.
a) type* p;
b) type *p;


(a) seems more logical, *except for one big problem*:
type* p1, p2;
won't mean what it looks like it should mean.
Use (b) therefore unless you're looking for trouble.

Someone else wrote
return foo(bar);

it is unusual to return another function's return value.


Hunh? I do it all the time. Admittedly I soemtimes end up
rewriting it, if only for debug purposes.

James
Nov 14 '05 #12

P: n/a
Papadopoulos Giannis <ip******@inf.uth.gr> wrote in message news:<bv***********@ulysses.noc.ntua.gr>...
Which do you think is best? []
a) return (var);
b) return(var);
c) return var;
If it's an expression then i'll return it in brackets else i'll return
the identifier.
a) a = (b+c);
b) a=(b+c);
c) a = b+c;
d) a=b+c;
If you program in languages that have different operator precedence
rules then brackets are helpful for clarity, IMO. I'd hold that
generally too.

The above is not so complex but, e.g., a=b*c/d*e+f can have many
meanings if you intend parts of the equation to be evaluated in a
certain sequence the language's operator precedence differs from.
6.
a) [function structure]


type function(type arg1)
{
declarations;

code;

return;
}

but as long as it's clear i don't mind.
Nov 14 '05 #13

P: n/a
Papadopoulos Giannis wrote:

Which do you think is best?

1.
a) type* p;
b) type *p;
b, because
type* p, q, r;
makes you want to think
type *p, *q, *r;

2.
a) return (var);
b) return(var);
c) return var;
c, why not ?

3.
a) return (ptr->var);
b) return(ptr->var);
c) return ptr->var;
c, same same.
4.
a) return (foo(ptr->var));
b) return(foo(ptr->var));
c) return foo(ptr->var);
c, same same.
5.
a) a = (b+c);
b) a=(b+c);
c) a = b+c;
d) a=b+c;
e) a = b + c;
6. E) type foo(type arg1, type arg2, ...) {
declarations; code;
return;
}


--
pete
Nov 14 '05 #14

P: n/a
Papadopoulos Giannis wrote:
Which do you think is best?

1.
a) type* p;
b) type *p;
b) for obvious reasons:

type* p, q;

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

c) there is no reason to put parentheses around expressions, otherwise
I would write

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

c) there is no reason to put parentheses around expressions, otherwise
I would write

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

c) here is no reason to put parentheses around expressions, otherwise
I would write

return (((foo)((ptr)->var)));
5.
a) a = (b+c);
b) a=(b+c);
c) a = b+c;
d) a=b+c;

None of the above. 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;
}


none of the above

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

code;

return Result;
}

and don't use \t to indent code that I post.

Kurt

Nov 14 '05 #15

P: n/a

"Papadopoulos Giannis" <ip******@inf.uth.gr> wrote in message
news:bv***********@ulysses.noc.ntua.gr...
Which do you think is best?

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


type* p

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.

As for braces, I know there is a "correct" way but doesn't indenting the
braces with the code make more sense?

if (...)
{
code;
}

makes more sense to me since an if() is followed by a statement which may or
may not be a compound statement. If you indent the statement, then the
braces (which are part of the compound statement, not part of the if()
should be indented as well. Also, the above is easier on the eyes to read
since you read the if() then read straight down the code. No jumping back
and forth.

Either way, I know it is personal preference.

Jim
Nov 14 '05 #16

P: n/a

"Jim Lambert" <ja*********@futrx.com> wrote in message
news:Fq****************@eagle.america.net...

"Papadopoulos Giannis" <ip******@inf.uth.gr> wrote in message
news:bv***********@ulysses.noc.ntua.gr...
Which do you think is best?

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

type* p

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.


So you'd write

type* p,
* q,
r;

???

That seems a bit odd...

Tom
Nov 14 '05 #17

P: n/a

"Tom St Denis" <to********@iahu.ca> wrote in message
news:dU******************@news01.bloor.is.net.cabl e.rogers.com...

"Jim Lambert" <ja*********@futrx.com> wrote in message
news:Fq****************@eagle.america.net...

"Papadopoulos Giannis" <ip******@inf.uth.gr> wrote in message
news:bv***********@ulysses.noc.ntua.gr...
Which do you think is best?

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


type* p

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.


So you'd write

type* p,
* q,
r;

???

That seems a bit odd...

Tom


No, I mean I would write...
type* p;
type* q;
type* r;

Jim
Nov 14 '05 #18

P: n/a
"Jim Lambert" <ja*********@futrx.com> wrote:

"Papadopoulos Giannis" <ip******@inf.uth.gr> wrote in message
news:bv***********@ulysses.noc.ntua.gr...
Which do you think is best?

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

type* p

I never use the comma operator since I have every variable on it's own line


Neither do those of use who have more identifiers on a line; those
commas are separators, not the comma operator...
As for braces, I know there is a "correct" way
Well, only for values of correct that amount to "agrees with me". Not
for values of correct that mean "can be proven to be the only right
one".
but doesn't indenting the braces with the code make more sense?

if (...)
{
code;
}


Ew, no! That way you're guaranteed to overlook the braces in a more
complicated compound statement.

Richard
Nov 14 '05 #19

P: n/a
Papadopoulos Giannis <ip******@inf.uth.gr> wrote in
news:bv***********@ulysses.noc.ntua.gr:
Which do you think is best?

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

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

3.
a) return (ptr->var);
b) return(ptr->var);
c) return ptr->var;
c but how is this notably different from 2?
4.
a) return (foo(ptr->var));
b) return(foo(ptr->var));
c) return foo(ptr->var);
c and again...
5.
a) a = (b+c);
b) a=(b+c);
c) a = b+c;
d) a=b+c;
e) 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;
}


d

--
- Mark ->
--
Nov 14 '05 #20

P: n/a
"Jim Lambert" <ja*********@futrx.com> wrote in
news:b6****************@eagle.america.net:
No, I mean I would write...
And here comes junior programmer dude... "I'll just add another pointer
type here..."

type* p, anotherPointer;
type* q;
type* r;


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

--
- Mark ->
--
Nov 14 '05 #21

P: n/a
"Mark A. Odell" <no****@embeddedfw.com> wrote in message
news:Xn********************************@130.133.1. 4...
"Jim Lambert" <ja*********@futrx.com> wrote in
news:b6****************@eagle.america.net:
No, I mean I would write...


And here comes junior programmer dude... "I'll just add another pointer
type here..."

type* p, anotherPointer;
type* q;
type* r;


"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. :-)

Nov 14 '05 #22

P: n/a
Nick Landsberg wrote:
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

Nov 14 '05 #23

P: n/a
Papadopoulos Giannis wrote:
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

Nov 14 '05 #24

P: n/a

"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
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.


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.
Nov 14 '05 #25

P: n/a
"Malcolm" <ma*****@55bank.freeserve.co.uk> wrote:

"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
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.
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.


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
Nov 14 '05 #26

P: n/a
On Tue, 27 Jan 2004 22:57:04 -0000, "Malcolm"
<ma*****@55bank.freeserve.co.uk> wrote:

"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
> 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.
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.


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

Nov 14 '05 #27

P: n/a
Richard Bos wrote:
"Malcolm" <ma*****@55bank.freeserve.co.uk> wrote:
.... snip ...
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.


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.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!

Nov 14 '05 #28

P: n/a
On Tue, 27 Jan 2004 22:57:04 -0000, "Malcolm"
<ma*****@55bank.freeserve.co.uk> wrote:
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.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #29

P: n/a

"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
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?

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

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.
Nov 14 '05 #30

P: n/a
Papadopoulos Giannis wrote:
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

--
gabriel
Nov 14 '05 #31

P: n/a
Papadopoulos Giannis wrote:
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!

--
gabriel
Nov 14 '05 #32

P: n/a
> 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.
Nov 14 '05 #33

P: n/a
Papadopoulos Giannis <ip******@inf.uth.gr> wrote:
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 ...;
}

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Nov 14 '05 #34

P: n/a
"Malcolm" <ma*****@55bank.freeserve.co.uk> wrote:
c) return foo(ptr->var);

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.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Nov 14 '05 #35

P: n/a
Paul Hsieh wrote:
Papadopoulos Giannis wrote:
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;


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.

Nov 14 '05 #36

P: n/a

On Wed, 28 Jan 2004, E. Robert Tisdale wrote:

Paul Hsieh wrote:
Papadopoulos Giannis wrote:
a) type* p;
b) type *p;
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


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

Nov 14 '05 #37

P: n/a
"Arthur J. O'Dwyer" <aj*@nospam.andrew.cmu.edu> wrote:
On Wed, 28 Jan 2004, E. Robert Tisdale wrote:
char c = 'c'; // character constant
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.
These *definitions* should be placed as close as possible
to the point where they are first used.


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.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Nov 14 '05 #38

P: n/a
Paul Hsieh wrote:
"Arthur J. O'Dwyer" <aj*@nospam.andrew.cmu.edu> wrote:
On Wed, 28 Jan 2004, E. Robert Tisdale wrote:
char c = 'c'; // character constant


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.


Why is mr. Tisdale hated so much??

PS. I am new to comp.lang.c

Nov 14 '05 #39

P: n/a
Papadopoulos Giannis <ip******@inf.uth.gr> scribbled the following:
Paul Hsieh wrote:
"Arthur J. O'Dwyer" <aj*@nospam.andrew.cmu.edu> wrote:
On Wed, 28 Jan 2004, E. Robert Tisdale wrote:
char c = 'c'; // character constant

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.

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.

--
/-- Joona Palaste (pa*****@cc.helsinki.fi) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"Normal is what everyone else is, and you're not."
- Dr. Tolian Soran
Nov 14 '05 #40

P: n/a

"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote in message
news:40**************@jpl.nasa.gov...
Paul Hsieh wrote:
Papadopoulos Giannis wrote:
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;


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

1. you declare variables where constants may be required,


Well I'm assuming you'd have one statement for constants and one for not.
E.g.

const char *p, c;
char q, *x;
2. your variables are undefined and
So far. That's just the declaration my friend.
3. your variables are undocumented.
True that. But it depends. Sometimes variables are trivial, e.g. "int x"
would often be just a "I want to step through an array".
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.


Your style is just plain messy. Try writing a function that has say 10 or
so variables. Now try maintaining 400 similar functions ;-). Giving them
values initially is just plain bad coding [hint constants other than trivial
ones should be #define not set in local variables].

I think this is just another "bad advice post" which you seem good at...

Tom
Nov 14 '05 #41

P: n/a
Papadopoulos Giannis wrote:
Paul Hsieh wrote:
"Arthur J. O'Dwyer" <aj*@nospam.andrew.cmu.edu> wrote:
On Wed, 28 Jan 2004, E. Robert Tisdale wrote:

char c = 'c'; // character constant

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.


Why is mr. Tisdale hated so much??


As Joona has said, because of his virtually universal bad advice,
and especially because of his habit of altering quotations of
other posters. This means he has to be watched and rebutted
continuously, just so newbies such as yourself don't get
misinformed. We can't just plonk and forget him. Like
BullSchildt, he often sounds good to the uninformed.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #42

P: n/a
On Thu, 29 Jan 2004 12:25:18 +0000, CBFalconer wrote:
Papadopoulos Giannis wrote:
Paul Hsieh wrote:
> "Arthur J. O'Dwyer" <aj*@nospam.andrew.cmu.edu> wrote:
>> On Wed, 28 Jan 2004, E. Robert Tisdale wrote:
>>
>>> char c = 'c'; // character constant
>>
>> 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.


Why is mr. Tisdale hated so much??


As Joona has said, because of his virtually universal bad advice, and
especially because of his habit of altering quotations of other posters.
This means he has to be watched and rebutted continuously, just so
newbies such as yourself don't get misinformed. We can't just plonk and
forget him. Like BullSchildt, he often sounds good to the uninformed.


For what it's worth, as a lurker who seldom posts, I don't hate Tisdale at
all. He's one of the posters I sometimes look for in clc, if he's gotten a
response from a clued regular. He is most certainly a troll, and most of
his "advice" is ludicrous, but this means he often provides a laugh. Also,
because (as Chuck says) clued regulars rebut him, newbies get to see some
good advice as a result of ERTroll's bad advice. OTOH, his dishonest habit
of editing others' posts is disturbing. It's one thing to know that you
shouldn't trust what he says. It's much worse to know that you can't trust
that people have said what he quotes them as saying. Perhaps he could get
a job with a major U.S. newspaper.

Nov 14 '05 #43

P: n/a
Papadopoulos Giannis wrote:

<snip>
Why is mr. Tisdale hated so much??
"Hate" is, in my opinion, too strong a word. Suffice to say that his
knowledge of C is rather shaky, compared to his determination to give
advice about it. If he could only learn, he might even become... well,
given his past track-record, there is no point in speculating on that
possibility.
PS. I am new to comp.lang.c


For a while at least, read every article you find. After a while, you'll get
a feel for who knows what they're talking about and who doesn't.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #44

P: n/a
Tom St Denis wrote:
Well I'm assuming you'd have one statement for constants and one for not.
E.g.

const char *p, c; cat main.c #include <stdio.h>

int main(int argc, char* argv[]) {
const char *p, c;
p = NULL;
c = 'c';
return 0;
}
gcc -Wall -std=c99 -pedantic -o main main.c

main.c: In function `main':
main.c:6: warning: assignment of read-only variable `c'

Nov 14 '05 #45

P: n/a

On Thu, 29 Jan 2004, Paul Hsieh wrote:

"Arthur J. O'Dwyer" <aj*@nospam.andrew.cmu.edu> wrote:
On Wed, 28 Jan 2004, E. Robert Tisdale wrote:
char c = 'c'; // character constant
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.


Yeah, sometimes that works for me, too. ;-) I was just reading
on autopilot, and was jolted awake by the incredibly bad advice
Trollsdale was dishing out.

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)


Funny, I'd say the opposite -- the association of the "*" is
absolutely, positively NON-controversial! It's dictated by an
international standard, for Pete's sake! ;) The controversial bit
of your post was where you seemed to advocate writing

char c, *p, q, *x;

or whatever it really was; I'm not going to take the time to look
back right now. I maintain that this is a Bad Idea.
Also, its not contrived -- go download Bstrlib and see for yourself.
I don't see any Bad Idea declarations in the CVS tree for bstrlib
at first glance. You do use 'int i,j;' and 'int i,v,n;' several times,
but I hope you can appreciate that declaring two or three closely
related objects of the same type on a single line is a far cry from
declaring four or five objects of different types on the same line!
As it happens, I *would* have re-written

bstring bBase64Encode (const bstring b) {
int i, c0, c1, c2, c3;
as
bstring bBase64Encode (bstring b)
{
int c0, c1, c2, c3;
int i;

which IMHO even without the (IMVHO) more-readable indentation makes
it more obvious that 'i' is unrelated to 'c0' etc. [And yes, IMO
it does *not* make more sense to use a four-element array here,
just in case anyone was going to piggy-back on this post. ;-) ]

But when I was talking about Bad Ideas, I was thinking of the common
newbie and ancient-scientific-code practice of writing

/* 3d**************@news.tin.it */
int compare(FILE* , FILE* , long* , long* ), j;

/* 6e******************************@loc...rogramming.com */
float sig_in[30], numerator[3], denominator[3], x[3], y[2], s_out[30];

which is just plain write-only code.

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


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.


If you remove the line I underscored above, your comment makes sense
and is true. I don't know why you added that second line, though --
it doesn't make any sense at all. Define variables when you need
them, and not [too far] before. As a corollary, if you find you need
an arbitrarily complex initialization scheme, it makes sense to put
that initialization in a function and write

struct myADT foo;
myADT_initialize(&foo, bar, baz, quux);

bstrlib does not seem at a glance to suffer from this problem, though.

-Arthur
Nov 14 '05 #46

P: n/a
Arthur J. O'Dwyer wrote:
Define variables when you need them, and not [too far] before.
As a corollary,
if you find you need an arbitrarily complex initialization scheme,
it makes sense to put that initialization in a function and write

struct myADT foo;
myADT_initialize(&foo, bar, baz, quux);


This is very bad advice because you can't define a const struct myADT.
Instead, you should implement a "pseudoconstructor":

struct myADT myADT_create(Bar, Baz, Quux);

so that you can define a constant:

const struct myADT foo = myADT_create(bar, baz, quux);

Or you could use it to define a variable:

struct myADT foo = myADT_create(bar, baz, quux);

and define a function

struct myADT* myADT_modify(struct myADT*, Bar, Baz, Quux);

so that you can *modify* the variable:

myADT_modify(&foo, bar, baz, quux);

Note that the myADT_modify function returns a pointer to foo so that
it can be used in any expression where &foo might otherwise appear
subsequent to the application of myADT_modify.

Nov 14 '05 #47

P: n/a

On Thu, 29 Jan 2004, E. Robert Tisdale wrote:

Arthur J. O'Dwyer wrote:

struct myADT foo;
myADT_initialize(&foo, bar, baz, quux);
This is very bad advice because you can't define a const struct myADT.
Instead, you should implement a "pseudoconstructor":

struct myADT myADT_create(Bar, Baz, Quux);

so that you can define a constant:

const struct myADT foo = myADT_create(bar, baz, quux);


That's good advice. I myself religiously avoid returning struct
types by value, and I also rarely 'const'ify anything anyway
(preferring to #define CONSTANT if it's never going to change, or
make a static global 'Constant' if the user might want to change
it, or make it a parameter if it's local to a function). However,
*if* one wanted to make a 'const struct myADT', this would be an
excellent way to do so.

Or you could use it to define a variable:

struct myADT foo = myADT_create(bar, baz, quux);

and define a function

struct myADT* myADT_modify(struct myADT*, Bar, Baz, Quux);

so that you can *modify* the variable:

myADT_modify(&foo, bar, baz, quux);

Note that the myADT_modify function returns a pointer to foo so that
it can be used in any expression where &foo might otherwise appear
subsequent to the application of myADT_modify.


Yes. I tend to use this more C++-looking idiom with pointers,
occasionally:

struct myADT *foo = new_myADT(bar, baz, quux);
myADT_modify(foo, bar, baz, quux);
delete_myADT(foo);

but it is a widely followed practice to let functions operate
on "buffers" rather than "OO objects" when writing in C. That
is, it becomes the caller's responsibility to allocate space for
a "buffer" object, on which the function operates; rather than
the function's responsibility to allocate a temporary struct
object and then copy the data over to the caller [which in C is
done automagically, but still has to happen somewhere].
I hope that makes sense. IOW: both ways work, and have their
uses, but I find my way more sensible more often -- in my code,
of course.

-Arthur
Nov 14 '05 #48

P: n/a
Arthur J. O'Dwyer wrote:
I tend to use this more C++-looking idiom with pointers,
occasionally:

struct myADT *foo = new_myADT(bar, baz, quux);
myADT_modify(foo, bar, baz, quux);
delete_myADT(foo);

but it is a widely followed practice to let functions operate
on "buffers" rather than "OO objects" when writing in C.
That is, it becomes the caller's responsibility to allocate
space for a "buffer" object, on which the function operates;
rather than the function's responsibility
to allocate a temporary struct object
and then copy the data over to the caller
[which, in C, is done automagically
but still has to happen somewhere]. I hope that makes sense.


That's just the point.
It isn't necessary for the C *programmer*
to explicitly allocate a "buffer" object.
This is done automatically by your optimizing C *compiler*.
Almost all modern C compilers implement
the Named Return Value Optimization (NRVO).
The function does *not* "allocate a temporary struct object
and then copy the data over to the caller".
Instead, it recognizes the temporary
as a reference to the return value and initializes it directly.
In the definition of object foo:

struct myADT foo = myADT_create(bar, baz, quux);

the optimizing C compiler allocates [automatic] storage for foo
then passes a pointer to foo as a [hidden] argument to myADT_create
which is used to reference to the return value.
*No* copies of a struct myADT are ever required.

No delete_myADT function is required
but the implementation should provide a function

void myADT_destroy(const struct myADT* p) {
}

which should be called

myADT_destroy(&foo);

before the thread of execution passes out of the scope of foo
in case the struct myADT is ever redefined to include a pointer
to an object allocated from free storage when it is created.

Note that you still need myADT_new (and myADT_delete)
to create objects that must survive the current scope.

Nov 14 '05 #49

P: n/a
> char c, *p, q, *x;

or whatever it really was; I'm not going to take the time to look
back right now. I maintain that this is a Bad Idea.


What do you think of
char , *p[], q(), *x;
then? :)

Recently I wrote some code like:

const unsigned char s[] = {
foo(1),
foo(2),
/* ... (about 10 entries) */
}, *ps = s;

so that later on I could iterate with ps, or use the results
from the functioncalls in many places. Using this syntax
avoided having to type out "const unsigned char" twice (or use typedef)
Nov 14 '05 #50

63 Replies

This discussion thread is closed

Replies have been disabled for this discussion.