📄 c-lesson.8
字号:
LOGICAL variable is said to be true when it is non-zero. So let's set a
variable to be TRUE.
00000000000000000000000000000001 A word representing TRUE.
Now let's do a logical NOT !.
00000000000000000000000000000000 There is a all zero word, a FALSE.
00000000000000000000000000000001 That word again. TRUE.
Now for a bitwise complement ~.
11111111111111111111111111111110 Now look we've got a word which is
non-zero, still TRUE.
Is this what you intended?
4) It is very easy to fall into the hole of getting the
'{' & '}'; '[' & ']'; '(' & ')'; symbol pairs all messed up and the
computer thinks that the block structure is quite different from that
which you intend. Make sure that you use an editor which tells you the
matching symbol. The UNIX editor vi does this provided that you turn
on the option. Also take great care with your layout so that the block
structure is absolutely obvious, and whatever style you choose do take
care to stick by it throughout the whole of the project.
A personal layout paradigm is like this:
Example 1.
function_type function_name ( a, b )
type a;
type b;
{
type variable_one, variable_two;
if ( logical_expression )
{
variable_one = A_DEFINED_CONSTANT;
if ( !return_value = some_function_or_other ( a,
variable_one,
&variable_two
)
)
{
error ( "function_name" );
exit ( FAILURE );
}
else
{
return ( return_value + variable_two );
}
} /* End of "if ( logical_expression )" block */
} /* End of function */
This layout is easy to do using vi with this initialisation script
in either the environment variable EXINIT or the file ${HOME}/.exrc:-
set showmode autoindent autowrite tabstop=2 shiftwidth=2 showmatch wm=1
Example 2.
void printUandG()
{
char *format =
"\n\
User is: %s\n\
Group is: %s\n\n\
Effective User is: %s\n\
Effective Group is: %s\n\n";
( void ) fprintf ( tty,
format,
passwd_p->pw_name,
group_p->gr_name,
epasswd_p->pw_name,
egroup_p->gr_name
);
}
Notice how it is possible to split up format statements with a '\' as
the last character on the line, and that it is convenient to arrange
for a nice output format without having to count the
field widths. Note however that when using this technique that the '\'
character MUST be the VERY LAST one on the line. Not even a space may
follow it!
In summary I *ALWAYS* put the opening brace on a new line, set the tabs
so that the indentation is just two spaces, ( use more and you very quickly
run out of "line", especially on an eighty column screen ). If a statement
is too long to fit on a line I break the line up with the arguments set out
one to a line and I then the indentation rule to the parentheses "()"
as well. Sample immediately above. Probably as a hang-over from a particular
pretty printing program which reset the indentation position after the
printing of the closing brace "}", I am in the habit of doing it as well.
Long "if" and "for" statements get broken up in the same way. This is
an example of it all. The fragment of code is taken from a curses oriented
data input function.
/*
** Put all the cursor positions to zero.
*/
for ( i = 0;
s[i].element_name != ( char *) NULL &&
s[i].element_value != ( char *) NULL;
i = ( s[i].dependent_function == NULL )
? s[i].next : s[i].dependent_next
)
{ /* Note that it is the brace and NOT the */
/* "for" which moves the indentation level. */
s[i].cursor_position = 0;
}
/*
** Go to start of list and hop over any constants.
*/
for ( i = edit_mode = current_element = 0;
s[i].element_value == ( char *) NULL ;
current_element = i = s[i].next
) continue; /* Note EMPTY statement. */
/*
** Loop through the elements, stopping at end of table marker,
** which is an element with neither a pointer to an element_name nor
** one to a element_value.
*/
while ( s[i].element_name != ( char *) NULL &&
s[i].element_value != ( char *) NULL
)
{
int c; /* Varable which holds the character from the keyboard. */
/*
** Et Cetera for many lines.
*/
}
Note the commenting style. The lefthand comments provide a general
overview of what is happening and the righthand ones a more detailed view.
The double stars make a good marker so it is easy to separate the code and
the comments at a glance.
The null statement.
You should be aware that the ";" on its own is translated by the compiler
as a no-operation statement. The usefullness of this is that you can do
little things, such as counting up a list of objects, or positioning a pointer
entirely within a "for" or "while" statement. ( See example above ).
There is, as always, a flip side. It is HORRIBLY EASY to put a ";" at the
end of the line after the closing right parenthesis - after all you do just
that for function calls! The suggestion is to both mark deliberate null
statements with a comment and to use the statement "continue;". Using
the assert macro will pick up these errors at run time.
The assert macro.
Refer to the Programmers Reference Manual section 3X and find the
documentation on this most useful tool.
As usual an example is by far the best wasy to explain it.
/* ----------------------------------------- */
#ident "@(#) assert-demo.c"
#include <stdio.h>
#include <assert.h>
#define TOP_ROW 10
#define TOP_COL 10
main()
{
int row, col;
for ( row = 1; row <= TOP_ROW; row++);
{
assert ( row <= TOP_ROW );
for ( col = 1; col <= TOP_COL; col++ )
{
assert ( col <= TOP_COL );
printf ( "%4d", row * col );
}
printf ( "\n" );
}
}
/* ----------------------------------------- */
Which produces the output:-
Assertion failed: row <= TOP_ROW , file assert-demo.c, line 15
ABORT instruction (core dumped)
It does this because the varable "row" is incremented
to one greater than The value of TOP_ROW.
Note two things:
1) The sense of the logical condition. The assert is asserted
as soon as the result of the logical condition is FALSE.
Have a look at the file /usr/include/assert.
Where is the ";" being used as an empty program statement?
2) The unix operating system has dumped out an image of the executing
program for examination using a symbolic debugger. Have a play with
"sdb" in preparation for the lesson which deals with it in more
detail.
Lets remove the errant semi-colon, re-compile and re-run the program.
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100
Here's the ten times multiplication table, for you to give to to
the nearest primary-school child!
I would agree that it is not possible to compare the value of a program
layout with a real work of fine art such as a John Constable painting or
a Michaelangelo statue, I do think a well laid out and literate example of
programming is not only much easier to read and understand, but also it
does have a certain aesthetic appeal.
Copyright notice:-
(c) 1993 Christopher Sawtell.
I assert the right to be known as the author, and owner of the
intellectual property rights of all the files in this material,
except for the quoted examples which have their individual
copyright notices. Permission is granted for onward copying,
but not modification, of this course and its use for personal
study only, provided all the copyright notices are left in the
text and are printed in full on any subsequent paper reproduction.
--
+----------------------------------------------------------------------+
| NAME Christopher Sawtell |
| SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.|
| EMAIL chris@gerty.equinox.gen.nz |
| PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) |
+----------------------------------------------------------------------+
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -