New questions and answers will be added at the end. This means that the questions are not organized into topics. I hope that the list isn't long enough to make this too big a problem, and I think it's more important for people to be able to read only the new stuff, by scrolling down to the end.
Q: I uploaded my file at 11:45 last night [October 10th] and it didn't work at CDF, but it worked fine at home. May I have an extension on account of this?
A: No. It's simply not possible for us to accommodate problems with your own computer equipment. We suggest that you use the CDF computers, which are professionally managed, and which have a good C compiler which correctly implements the C programming language. Use of your own equipment is at your own risk; I can sometimes assist you with it, and I'm not opposed to it, but if problems with your own computer were allowed to cause you to have extensions, everyone would have free extensions. It's just not feasible.
At this date [October 11th] it's a bit late for this information to be of use to you for assignment one. Fortunately I have a time-warp here so I'll post this on the CSC 270 web pages retroactively on September 24th. Please be advised.
Q: How do I compile multiple files together into one program?
A: List multiple files on the command line. For example,
gcc -Wall -ansi -pedantic testdiffeq.c diffeq.c -lmOr just type "make" to use the supplied Makefile. (We'll discuss writing Makefiles just very briefly, later in the course, or perhaps only in tutorial. For those of you who have the King book, there is a chapter about Makefiles.)
Q: When I use any math library function, I get an error that that function name is an "undefined symbol", and something about a reference. But I am #including <math.h>!
A: math.h supplies the extern declaration for the function, like "extern double pow(double x, double y)". That is important. Equally important (arguably more so, although actually both are essential) is to supply the code for the math functions.
The situation here is similar to that involved in your call of delist() from main(). You have to declare delist() in diffeq.c (actually via #include "diffeq.h"), and you have to "link" with the definition of delist() in diffeq.c.
Similarly, you have to link with the math library explicitly, if you call any functions in it. You do this by putting "-lm" at the end of your "cc" (or "gcc") command line, e.g. "cc testeq.c diffeq.c -lm". "-lm" is short for something like "/usr/lib/libm.a". These .a files are just collections of .o files, but the special rule is that the compiler only takes out the object files from libraries which satisfy as-yet-unsatisfied references from the other files. The idea is that when you call, say, the pow() function, then obviously the code for that function has to be included in your executable; but your executable does not have to swell by the size of the entire math library, just the parts you use. Thus "-lm" has to be last (or, to be precise, it has to be after at least one file which calls each function in the math library which is called from any of your files -- easiest simply to put it last always (although we do sometimes have to worry about this sort of thing when we link with multiple libraries which reference each other)).
So why don't you need to link with the stdio library to call printf, and all sorts of other libraries for the other library functions you might be calling? Because a great many libraries are in a big conglomerate library called the "C library", and the C library is linked with by default. That is to say, "-lc" is implied at the end of your cc command line. You must specify any other libraries explicitly. Except that so many of them are rolled into the C library. The math library, however, is not part of the C library, and thus must be requested explicitly.
Q: Can I use the pow() library function?
A: Yes. But if you want the function ex, that's exp(x).
Q: Well gosh, how do I find out what a library function does? I thought that exp() was something else.
A: Every library function has a unix "man page" ("man" is short for "manual"). You can read the exp man page by typing "man exp".
A2: Look it up in the index of your C book, if you have one. Your C book might have a list of commonly-called functions (which would be more useful than a list of absolutely all library functions).
Q: I want to add a "helper" function in diffeq.c. Do I add its extern declaration into diffeq.h?
A: No, for two reasons. First of all, you do not submit diffeq.h. We will compile your program with the original diffeq.h. But most of all, diffeq.h is intended to be a list of functions which are "exported" from diffeq.c, like "public methods" in Java. If something is analogous to a "private method" (or private instance variable), in C we would not put its extern declaration in the .h file, but rather we would put it right there in the .c file so that it is only accessible to other functions in that .c file itself. In C, the file level is the closest thing we have to a class.
(Actually there is a keyword "static", which means two different things in C (they got stingy about allocating new keywords), but in the case of a function declaration it always means that it is not made available to other files. This keyword is quite underused in C and we won't expect you to use it in this course; sooner or later we'll be moving to C++ and using real classes again. However, the sample solution for assignment one will use "static" properly and you can see how it works at that point.)
Q: Do I have to limit the length of the lines to 80 characters, as I did in CSC 148?
A: Yes. The printer, my computer monitor, etc, are all of finite width.
The standard terminal width is 80 characters; all you can expect from me in
terms of line width, e.g. in how I format the print-outs, is that I make 80
characters or fewer look acceptably. If lines are longer than that,
they will wrap around. Instead, you should wrap them around yourself, taking
care to make the result tidy and readable.
Q: My program works perfectly but when compiled, there are error or warning
messages. Can I leave it like this?
A: No.
(Well, when the due time approaches, you should submit whatever you've got;
but if you have time, you should correct these errors.)
Warning messages indicate that you are doing something improper. It may
fail to work on other C compilers, for example (whether this is what's going
on depends on the
particular error message).
In this course we are writing careful, correct, tidy, and maintainable
C programs.
Last year, ajr wrote
a newsgroup article about this, which the above
paragraph is from.
Q: I changed the statement
A: You are mistaken about efficiency.
The second version will likely run slower than the first,
and it will produce a larger compiled program,
and it is more likely to contain errors (bugs),
and future modification to this program is more likely to introduce bugs
because of its unnecessarily complex structure.
The most important thing,
both in this course and in "real life",
is to write your program clearly and correctly.
Many times when people modify their programs in this sort of way for
"efficiency" they cause harm and no good.
That is, the best you can hope for is that the program works almost as well as
before.
There's a saying: "The first rule of optimization is: Don't."
You will have noticed that many large software projects produce programs which
are abominably slow.
The solution, though, is not to perform "micro-optimizations" of this kind;
they may or may not help, but any help will be imperceptible and won't fix the
situation.
The main way one speeds up unacceptably-slow programs to an acceptable speed
is to improve the algorithms.
This is much harder when "micro-optimizations" are in place.
Occasionally one does perform these sorts of micro-optimizations, when you're
trying to speed up a program in every last possible way.
But you do them last, and you only micro-optimize the sections of the code
which profiling data has shown to be worth the cost.
(Usually this is no code at all; i.e. you don't do it.)
The cost is substantial: it creates difficulty reading and working with the program.
The benefit of most micro-optimizations is basically zero.
Zero benefit for substantial cost is not a good tradeoff.
Q: How do I check whether or not my files have been submitted properly?
A: Type the following command:
This command does not give you the file contents, but it gives you the file
size, so you can compare to an "ls -l" of that file and verify whether or not
it's the correct one, and you can see whether all your files have been
submitted.
You can resubmit a file by simply submitting a file by the same name again.
The last one counts.
Q: I have both a course account and a "permanent" account. Does it matter
which one I submit from?
A: Two answers: "No" in that if you submit successfully, you're ok;
"Yes" in that I believe that the submission system will actually let you
submit from only one of the two accounts.
This will probably be the course account.
If the submission works, and "submit -l -c csc270h -a a1" shows your files,
then they'll get graded.
Q: What are those things like "#define TABLELINES 100" in diffeq.h?
A: This is a facility of C used for constants. It is part of the "C
pre-processor", like #include. We'll be discussing the C pre-processor in
more detail later in the course (briefly).
It is basically a global substitution. After "#define TABLELINES 100", every
time "TABLELINES" appears, it is replaced by "100" (without the quotes).
Why not simply use
"const int TABLELINES = 100;"?
Because in that case, TABLELINES would not
be able to be used as an array dimension in ANSI-standard C.
"const"s in C are not actually what we normally think of as a "const"
in a programming language.
They were added by the ANSI standardization committee and they don't
fit with the language too well in some ways.
(C++ does not have this quirk; C++ "const"s can indeed be used as array
dimensions.)
Your diffeq.c should function as appropriate when TABLELINES and/or STEPSIZE
are replaced with any reasonable values.
This is a way in which our test program can parameterize your assignment
submission.
That is, you do have to use them.
Q: So, couldn't STEPSIZE have been a const, at least?
A: Yes, it could have been. But C programmers are used to the uselessness of
const and thus they tend to use #define.
Q: I get some errors when compiling with -ansi and/or -pedantic, but not when
compiling only with -Wall. Do I have to fix them?
A: Yes, you have to fix them. Your program should compile with no errors or
warnings when compiled with "gcc -Wall -ansi -pedantic testdiffeq.c diffeq.c",
using our supplied testeq.c and our supplied diffeq.h.
(Also see the q&a above about warning messages,
and the above-cited newsgroup article.)
Q: What does "ISO C89 forbids mixed declarations and code" mean?
A: It means that within a given scope, all declarations must precede all
non-declaration statements. For example,
Q: That rule is stupid!
A: Yes, it is. As a matter of fact, it's much less stupid than similar rules
in most programming languages at the time C was originally invented, but it
looks very stupid today.
C++ allows the "mixing" of declarations and non-declaration statements.
So does the newest C standard, but we're not using that for this course (yet).
Please compile with "-ansi" to enforce adherence to the original C standard in
this course, for assignments one and two. (Assignments three and four will be
in C++, which, among other things, eliminates this silly restriction about
declarations having to be at the beginning of a scope.)
Q: What do compiler warnings about "carriage return" mean?
A: They mean that there are spurious control-Ms in your file. Control-M in
the ASCII standard is called "carriage return".
These control characters probably arose because you transferred your file
incorrectly from ms-dos to unix. The ASCII standard does not specify how
lines of a text file are separated. In ms-dos, the line terminator is the two
characters control-M and control-J (in that order). In unix, the line
terminator is
the single character control-J. When you transfer text files between
computers, the file transfer program should have an option to change the line
terminator character appropriately.
If you transferred your file in the wrong mode, you can fix it up with the
"flip" command, as described in the Student Guide to CDF, page 13 ("Removing
line feeds").
Q: The examples in the King book say "main()" instead of "int main()".
Which one is right? And why do both of them seem to work?
A:
There's a rule in C which is mostly historical and is quite silly, which says
that the default type for things is int. In particular, the code
Almost everyone agrees that the latter form is bad. However, some people make
an exception for main() for historical reasons. I think that this exception
is pointless but harmless.
However,
leaving off an "int" in any function declaration other than main() is
certainly grounds for a complaint by the grader.
And since gcc -Wall -ansi -pedantic will
indeed give you an error (warning) message for
leaving off the "int" in the declaration of main(),
you should put the "int" in there too.
The fact that you are/were allowed to leave out the word "int" in declaring a
function to have return type int has led to two quite separate uses of this
laxness.
For one, some C programmers used to omit the type declaration to indicate that
no value was returned, especially in the very early days before the "void"
type was added to the language.
However, other C programmers got used to leaving off the "int" just because
you could.
This means that other than in the case of main(), you really don't know what
is meant by a missing type declaration these days.
If you mean that the function returns int, say "int";
if you mean that the function doesn't return anything, say "void".
This is why the modern version of gcc gives a warning if "return type
defaults to 'int'".
Q: What is a "parse error"?
A: You may know that as a "syntax error".
To anthropomorphize slightly,
the text has sufficiently little
resemblance to a C program that the compiler doesn't know where to begin with
it.
But I can also give you a more specific answer.
Many of these for assignment one are being caused by people using "//"-style
comments.
You should use the "/* ... */" style of comments.
People are especially experiencing this if they've developed their code on a
"C compiler" at home, and
it's exactly the reason we recommend against using random other C compilers
out there -- they may implement "extensions" which allow you to write things
which aren't standard C.
If you have an "always-on" type of internet access from home,
e.g. ADSL (sympatico) or cable modem, then I recommend that you use the CDF
computers from home rather than a compiler on your home machine.
See
http://www.dgp.toronto.edu/~ajr/270/remotelogin.html
for terminal program recommendations -- you don't need to install anything as
complex as Cygwin or similar.
(In fact the "//" style of comments has been added in the latest C standard,
but we're not using that version of C for this course (yet). You may not
think that 1999 is so recent, but if you look at
http://gcc.gnu.org/gcc-3.1/c99status.html
you will see that GCC does not yet support the full ISO 1999 C standard,
so by that measure it's still too new to use in this course.)
(There's a good chance that that's not why your home C compiler accepts
"//" comments anyway. A lot of compilers accept extra things which the
authors thought were cool. "//" comments may indeed be cool, but in this
course we are expecting you to write programs which will run correctly
anywhere because they adhere to the standard C programming language.
The GCC authors are not immune to this coolness disease, but if you compile
with both -ansi and -pedantic, it suppresses any unwarranted coolness.)
x += y;
to
if (y == 1)
x++;
else
x += y;
, but this is harder to read.
Which is more important, efficiency or "style"?
submit -l -c csc270h -a a1
That "-l" is the letter L (but lower-case), not the number 1.
It is like the "-l" in "ls -l".
int something(int x)
{
int y = 3;
x *= 2;
int z = x + y;
...
must be re-written as
int something(int x)
{
int y = 3;
int z;
x *= 2;
z = x + y;
...
int gloop()
{
return 3;
}
is exactly the same, by definition, as
gloop()
{
return 3;
}
[main course page]