Stylistic questions on UNIX C coding.

I

Ike Naar

I call a strawman; a proper c-style will not allow the first form;
e.g., at Sun our style requires this form:

if (sscanf(input_buffer, "%d %d %d", &length, &width, &height) == 3 &&
sscanf(other_buffer, "%d %d %d", &color, &price, &weight) == 3 &&
needs_processing(color)) {
compute_volume(length, width, height);
compute_something_else(price, weight);
}

I don't think your strawman call is justified.
My "first case" is the output of (gnu) "indent -kr".
 
J

Jonathan de Boyne Pollard

Cost of a line feed is the same as the cost of a space character
That is only the case when one's terminal is set to NL0 mode and isn't
set to ONLCR or ONLRET modes, or it is set to both CR0 and NL0 modes.
 
N

Nick Keighley

we may be talking at cross purposes as well as disagreeing. We also
may be starting to repeat ourselves. Editors and code layouts are very
personnel things.



ok. A <tab> character is ASCII 9 if found in source text (I know the
world isn't ASCII, but a bit of concreteness here makes life a little
easier). A <tab> is also a key on many keyboards. I'll try and

that is there are said:
And variable, to the individual coder's tastes, simply by their choice of
tab stops, without messing it up for everyone else.  Yes, indeed, tab-
stop dependent, not "whatever number of spaces I think should be inserted
here" dependent.

one difficulty with embedded <tab-chars> as the only layout character
is that you lose fine control.

void pippo (int n)
{
if ((n == PHOTON) ||
(n == LEPTON) ||
(n == HADRON))
{
send_msg ("claim nobel!");
}
}

I don't see how this layout can survive spaceless layout or variable
tab stops. Presumably you don't require layout like this.
I have a better editor.  
:)


One that understands the difference between
spaces and tabs.  One that does *not* do something as brain-dead as
deleting _multiple_ characters when I press delete once.  Any editor
which deletes multiple items on a single delete simply cannot be trusted,
it's liable to destroy something.

no. My editor (this is actually a configurable option) only does this
for spaces. I assure you it works well in practice.

If I hit the <tab-key> it inserts N spaces. I still use the <tab-key>
to indicate layout but the editor puts said:
No, sorry, we're using spaces here, not tabs.  If you want to insert
tabs, then by all means, use tabs.

If I want to insert <tab-chars> (eg. for the dreaded make file) I have
to change an option on my editor. Normally I do not want to insert
 But then you're on my side of the
fence, with spaces being defective by design for indent.

this is phrasing it rather strongly. There are plenty of people who
have a different opinion from you.
 If they weren't
defective by design, you wouldn't be using tab instead of space.

is that <tab-char> or <tab-key>?

<snip>

[it's getting repetitive]
If your editor - and the notion of spaces for indentation - weren't
defective by design, you wouldn't need to use a special key to insert
spaces; that's why you have a space bar.  The fact you have to resort to
something entirely different, the tab key, is prima facie evidence the
whole notion of spaces to indent is as defective as it appears.

this is opinion masquerading as fact. I use the <tab-key> to indicate
my layout requirement; the editor "compiles" this into <space>
characters. A one-to-one mapping of key to text is not a requirement
(plainly not or delete and backspace would always work the way I
wanted them to on Unix!).
Now, if your editor worked properly, using tabs instead of spaces, with
the tab key inserting tabs as it should, then when viewed on someone
else's display, rather than yours, it would show the code as *they*
prefer to view it, rather than as *you* have decided is the only true way
which everyone should be forced to view it in.

I like finer control over my layout than you do apparently
Really, isn't this just a case of imposing your own layout conventions on
others, rather than using a common sense approach which actually lets
everyone view the code in their own preferred manner?  Without having to
defeat the needless additional complication of converting some godawful
arrangement you happen to like into something actually manageable?

but you also require others to agree to your conventions.

I bet you'd hate this approach

Code laid out like this with 4 character indent
xxxx
yyyy
zzzz
wwww

and using S and T to represent the "layout charcaters" actually looked
like this

xxxx
SSSSyyyy
Tzzzz
TSSSSwwww


the worst or all possible worlds!
 
R

Richard Bos

Julienne Walker said:
It's only error prone if you have multiple variables in a declaration
statement (which the OP's example did not). That itself is often
viewed as an unsafe practice.

Incorrectly. I would much rather see

int x, y, z;
int *dx, *dy, *dz;

than

int x;
int y;
int z;
int* dx;
int* dy;
int* dz;

Richard
 
J

Julienne Walker

Incorrectly. I would much rather see

I'm sorry you disagree. Perhaps if you made it clear to everyone in
the world what you'd rather see, they'll change their beliefs to suit
your style. ;-)
 
I

Ian Collins

Julienne said:
I'm sorry you disagree. Perhaps if you made it clear to everyone in
the world what you'd rather see, they'll change their beliefs to suit
your style. ;-)

Eh? He did!
 
E

Eric Sosman

I'm sorry you disagree. Perhaps if you made it clear to everyone in
the world what you'd rather see, they'll change their beliefs to suit
your style. ;-)

I'm with Richard on this one. When you have a bunch of
"obviously related" variables of the same type, there's little to
be gained and something to be lost by strewing the declarations
over multiple lines.

double rx, ry, rz; /* position */
double vx, vy, vz; /* velocity */
double ax, ay, az; /* acceleration */

.... is, to my eye, a lot more readable than

/* position */
double rx;
double ry;
double rz;
/* velocity */
double vx;
double vy;
double vz;
/* acceleration */
double ax;
double ay;
double az;

Even when there are only two variables

int compare(const void *pp, const void *qq) {
const struct jimjam *p = pp, *q = qq;

.... seems preferable to the one-per-line alternative: It moves
briskly past the boiler-plate preliminaries and helps the
attention proceed to the business at hand.

On the other hand, I'd agree that

int count, statusflag, i, modelnumber, j, k, errno_save;

.... is objectionable.
 
I

Ike Naar

Personally, I dislike like if expressions that evaluate with side
effects, I would
declare temps and move the scanfs outside the if statement. It improves the
readability too.

But that was not the point; the point was to make the if condition too
large to fit on a single line. The expressions were chosen more or less
at random just to illustrate that point.
 
N

Nick Keighley

It is fine with the space but not without (if() vs if ())


the point I was making was that I put the space in front of the
bracket BOTH for 'if' AND for a function invocation.
 
C

Curtis Dyer

Horrifically wrong.

I think it's a good bet that Julienne meant that the OP should be
consistent *with a reasonable style*.
Just make sure you're consistent with
everyone else, and nobody will care.

I don't know of any one style that's completely consistent with
everyone else.

But overall, you make a good point, since abominations such as

char *
foo( char*
*x ) {
/* ... */
}

and

void
bar( int*
y ) {
/* ... */
}

are consistent, but consistently awful.
 
S

Stefan Ram

Eric Sosman said:
double rx, ry, rz; /* position */
double vx, vy, vz; /* velocity */
double ax, ay, az; /* acceleration */
... is, to my eye, a lot more readable than
/* position */
double rx;
double ry;
double rz;

You can have your cake and eat it, too:

double rx; double ry; double rz; /* position */
double vx; double vy; double vz; /* velocity */
double ax; double ay; double az; /* acceleration */
 
C

Curtis Dyer

As a fellow amateur in C....

Another fellow amateur, here. :)
While I use them I don't like all caps for #defined values for
two reasons

1) #defined values don't seem to me too far removed from global
parameters.

I'm not sure what you mean here by "global parameters". Perhaps you
mean object identifiers that have file scope? If so, one crucial
difference that stands out to me is that macros may not expand to
lvalues.

#define MaxFoo 512

/* ... */

int main(void)
{
/* ... */

MaxFoo++; /* Whoops */

/* ... */
}
Indeed if we change them to parameters in a function
call they lose upper case status.

Again, I'm not sure what you mean.
The two uses are similar. To
my mind the format of the names should also be similar.

2) I'd prefer to reserve all caps for macros. Then they serve as
a warning that parameters are not guaranteed to be evaluated
exactly once.

Another distinction is that you can't use macro identifiers exactly
like function identifiers:

qsort(data, nitems, sizeof *data, compar);
Many libraries use all caps for their constants.

I rather like Rob Pike's style and reasoning behind identifiers in
his _Notes on Programming in C_.

<http://www.lysator.liu.se/c/pikestyle.html>


I've occasionally seen:

char * firstname;
It's normally as the latter due to

char* FirstName, ch, *p;
char *FirstName, ch, *p;

As Eric Sosman noted elsethread, I find that it depends on the
context, whether or not I include multiple declarations on the same
line.

I generally like to place the asterisk next to the declarator for
object declarations. For function prototypes and definitions, I
like to place the asterisk next to the return type.
Regardless of which form is used I think only ch will be a char
variable
Right.

- i.e. "char*" can be misleading.

I think mainly to newcomers, but I can't imagine it being too
misleading for most C programmers.

That's much better than sprinkling messages throughout the code.
If followed consistently it makes clear what messages the code
can issue. Apart from clarity that would help if you ever want
to release your code in another human language. There are better
ways with more mechanism.

I believe some use enum constants, for example, as indexes for a
lookup table with error message strings.
You may need a way to include variable values in your messages.

Format strings for the *printf() functions is one obvious way.

As Julienne noted elsethread, the professionals are no more in
agreement, with regard to style, than the differing style guides.
Check some examples: K&R2, C Unleashed, books by Douglas Comer,
the Linux source etc. Also there is a FAQ entry for style
issues:

http://c-faq.com/style/index.html

Also, I would imagine lurking in comp.unix.programmer would be
another good way to pick up on common Unix coding styles, as well as
good practices in general.
 
J

Julienne Walker

I'm not sure what you mean here by "global parameters".

Most likely James meant the usual definition of a global variable in
C, which is an object with file scope and external linkage. But if
that's the case, and object macros are not too far removed from global
variables, we could make the same argument for literals, couldn't
we? ;-)
I think mainly to newcomers, but I can't imagine it being too
misleading for most C programmers.

I fail to see how char* x; is any more misleading than char *x;.
Either way the gotcha of char *x, y; still exists. Once you understand
the issue, it's a small matter of applying that knowledge. Of course,
char* x, *y; is pretty fugly, so the logical result is attaching to
the identifier in all cases (char *x, *y;), or splitting the
declarators across multiple statements: (char* x; char* y;).

Alternatively you could sidestep the issue with typedef:

typedef char* pchar;

pchar x, y;

Personally I'm not a fan of hiding levels of indirection behind a
typedef, but whatever floats your boat.

Ah, much ado about a trivial matter. Such is the way of clc. ^_^
 
N

Nick Keighley

Another fellow amateur, here.  :)

pre-processor macros have nasty semantics so its worth making them
standout.

I'm not sure what you mean here by "global parameters".  

nor me. If he meant "global variable" the that means either file scope
with internal linkage or file scope with external linkage. I suppose
"global parameter" might be one of these.

int adjust = 10;

int make_adjustment (int fiddle)
{
mass_adjust (adjust + fiddle);
}

void do_stuff (int bing)
{
adjust = 0;
make_adjustment ();
}


an abomination, but it happens (call backs without a needed parameter
are one excuse). I don't really see #defines as being like global
variables even though they have file scope.

Perhaps you
mean object identifiers that have file scope?  If so, one crucial
difference that stands out to me is that macros may not expand to
lvalues.

  #define MaxFoo 512

  /* ... */

  int main(void)
  {
    /* ... */

    MaxFoo++; /* Whoops */

    /* ... */
  }

well they can if you use them to alias an l-value

int max_foo;
#define MAXFOO max_foo

MAXFOO++

not a good idea but...
Again, I'm not sure what you mean.

me neither!


which two uses!

what? I thought you were explaining why you weren't using all caps for
macros?! Did you mean value macros and function-like macros?

#define MaxFoo 127
#define INC(X) (X++)

Another distinction is that you can't use macro identifiers exactly
like function identifiers:

  qsort(data, nitems, sizeof *data, compar);

why not? I just don't follow you.


oh yes! C programmers are nothing if not opinionated!

I think mainly to newcomers, but I can't imagine it being too
misleading for most C programmers.

the C++ people seem to mange ok

<snip>
 
N

Nick Keighley

[...] what do Windows
users use to enter and edit source code?
the IDE, ConText, emacs, Word
vi! Nowadays likely in its gvim incarnation, of course.
VI VI VI!
the editor of the beast

Well, when I used VI it was because there wasn;t anything
better on machine. Who said: VI editor that beeps and corrupts you
files?
Once I encrypted my source code by accident with that thing.


"The Real Programmer wants a "you asked for it, you got it"
text editor--complicated, cryptic, powerful, unforgiving,
dangerous. TECO, to be precise."
 
R

Richard Bos

You can have your cake and eat it, too:

double rx; double ry; double rz; /* position */
double vx; double vy; double vz; /* velocity */
double ax; double ay; double az; /* acceleration */

Yes, there's always _someone_ who prefers the worst of both worlds.

Richard
 
S

Stefan Ram

Kelsey Bjarnason said:
Frequently. Here's a tip: indent the ( to a tab stop. All lines up -
and allows the individual viewer to work to his own preferences.

The text

Talphabeta(T(
TTT(

, where »T« denotes a tab charater, will be rendered as

alphabeta( (
(

, when there are tab positions at 8, 16, 24, 32, and so on.
So now, the final parentheses of every line are aligned.

But with tab positions at 4, 8, 12, 16, 20, and so on, it
will be rendered as

alphabeta( (
(

So it is not possible to align characters of a line that
are not the first non-tab character of a line using tabs
in such a way that they will be aligned for every tab width.
 
B

bartc

Kelsey Bjarnason said:
Wait, you have to _reconfigure_ your editor to insert tabs when you hit
tab, because by default, pressing tab doesn't give you a tab, it gives
you spaces? What does spacebar give you? Ampersands? Lemme guess:
"enter" activates "close file without saving". And delete nukes anything
from zero to 8 characters.

On my typewriter, Tab moves the carriage up to the next tab-stop. Backspace
moves the carriage back, one space at a time.

So Tab is just a kind of macro on that machine.

To emulate the same behaviour in an editor, you don't want or need to store
actual tab characters, you just need the ability to quickly skip forward or
back to the next tab-stop position.

But one problem is ensuring the same set of tab-stops are used across
editors, or even across files in the same editor.

Yes. The tab key puts in tabs. The spacebar puts in spaces. Enter puts
in enter, 'Q' puts in 'Q' and so forth.

Printable characters tend to be inserted into the text. Non-printable chars
and special keys could do anything. I suppose Esc puts in escape characters
and F1 puts in 'F1' characters?
 

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

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top