Understanding some code

M

Moi

I would refuse to pay money to learn C from someone who wrote this. I
count three obvious errors plus a bewildering variety of crappy design
choices and badly-written code.


The design choices are the worst part of it, IMHO.
Of course the code is ugly, but that may be a way to teach
the students the value of readability.

I wish you the best of luck in your course. Know that you will be
learning C despite this idiot, not because of him.

Could be a nice way to force the students to think about style
and maybe discuss it.
The way literature is studied and discussed after learning a (natural) language.

AvK
 
U

Uno

I wish you the best of luck in your course. Know that you will be learning
C despite this idiot, not because of him.

-s

Well you could knock me over with a feather. It's very typical for
these teachers to put out code like this at the beginning of the term.
 
S

Squeamizh

Well you could knock me over with a feather.  It's very typical for
these teachers to put out code like this at the beginning of the term.

That hasn't been my experience. If you're right, that just means
there are a lot of sucky teachers.
 
M

Mark Bluemel

parjit said:
..We do not have to explain this code but I want to
understand it for my own interest. It is very complicated code, I don't
think I will ever be able to write code this clever :(

It's not clever code. It's code from someone who thinks they are clever.
 
N

Nick Keighley

in general leave some context in your posts. A post should be as far
as possible standalone.

[horrid code- is it homework?]
It is not a homework, it is code the teacher gave us to use as a
component in our homeworks to take care of error checking and unsafeness
in standard functions.

not unreasonable at the beginning of the course

We do not have to explain this code but I want to
understand it for my own interest.

good in principle. Unfortunately the code is a programming disaster.
This is not code for emulating, this is code for lying down and
avoiding.

It is very complicated code, I don't
think I will ever be able to write code this clever :(

Good! Actually you probably will one day (we were all you once).
Hopefully by that time you will be smarter than your teacher and know
not to do it!

<snip>

--

Unicode is an international standard character set that can be used
to write documents in almost any language you're likely to speak,
learn or encounter in your lifetime, barring alien abduction.
(XML in a Nutshell)
 
U

Uno

That hasn't been my experience. If you're right, that just means
there are a lot of sucky teachers.

You both undervalue the programming boner it gives a student to come up
with a "mistake" that the instructor has made. Sometimes I include a
mistake intentionally when I need code review, and I want to stack the
deck with who will likely respond. Usually, my inability to remember
syntax that I haven't worked in recently takes care of that by itself.
One thing I liked about being injured was the leisure to read dinkumware
an hour at a time.

I find it completely improbable that parjit doens't know to type main as
an int and talks of memory leaks from the other side of his mouth.

That safegets looked to me like a good arson: beautiful from a distance.
 
T

tim

Seebs gives himself to be this person who understands the learning
process, indeed can even divine what others are learning.
Seebs obviously can't divine, but he does give a lot of useful info for
people who are learning the finer points of C, for which I am quite
grateful at times.
And, here, he's answering somebody's homework. This is the first
worksheet the prof hands out.
Would love to know what courses you have done then: if that is your
experience, it is a million miles away from mine.
 
S

Seebs

Seebs obviously can't divine, but he does give a lot of useful info for
people who are learning the finer points of C, for which I am quite
grateful at times.

Thanks! I got a lot of help from people back when I was starting out,
and I figure the best thing to do is try to pass that on. Especially
now that I'm actually sort of competent to try to help. I wasn't
always so good. (I still suck at this in some ways, but I've learned
to mitigate them...)

Don't mind Uno, he's got a grudge of some sort.

-s
 
T

tim

Thanks! I got a lot of help from people back when I was starting out,
and I figure the best thing to do is try to pass that on. Especially
now that I'm actually sort of competent to try to help. I wasn't
always so good. (I still suck at this in some ways, but I've learned
to mitigate them...)
Maybe I'll try chipping in sometime in the future. I'm not exactly
useless at C but after a year and a bit in I still feel like a complete
idiot some days!
Don't mind Uno, he's got a grudge of some sort.
Grudge, chips, whatever. Seen some of his past posts: rather strange to
say the least...
Cheers, Tim.
 
S

Seebs

Maybe I'll try chipping in sometime in the future. I'm not exactly
useless at C but after a year and a bit in I still feel like a complete
idiot some days!

Usually a good sign -- most of the best programmers I know often feel like
idiots!

Here is the advice I wish people had given me way back when:

1. No fear! Or, as a German teacher used to tell us in school: Make
your mistakes with confidence! When we were unsure of what we wanted to
say, we tended to get quiet and mumble -- making it harder for him to
know whether we'd actually made a mistake. So. Go ahead and post
your thoughts, speculations, and opinions. Don't hem and haw. Say what
you believe.

2. Caveats! Feel free to qualify those statements a bit with "I am
not sure, but...".

This may sound contradictory, but... The point is that your warnings that
you aren't sure shouldn't detract from the clarity of what you're saying.
Better to write:
I'm not sure, but I think INT_MAX has to be at least 32,768.
than either:
INT_MAX has to be at least 32,768.
or
INT_MAX has to be somewhere over 30,000.

The first is good. The second could mislead an even-more-new newbie,
who wouldn't have any hints to check your work. The second is true, but
so vague as to be useless, and no one can correct you if you actually
meant 32,768 but weren't quite sure and didn't want to risk being wrong.

No shame in being wrong. Fixing mistakes is a big part of how people
learn effectively.

-s
 
T

tim

No shame in being wrong. Fixing mistakes is a big part of how people
learn effectively.

Very true, as I've learned with various work colleagues; some more
understanding than others.
Hope to show myself up here good style sometime in the future then!

Thanks, Tim.
 
S

Shao Miller

parjit said:
It is not a homework, it is code the teacher gave us to use as a
component in our homeworks to take care of error checking and unsafeness
in standard functions. We do not have to explain this code but I want to
understand it for my own interest. It is very complicated code, I don't
think I will ever be able to write code this clever :(
Perhaps the teacher will explain it later. Perhaps participants of a
class will discuss it. Perhaps the function's body will evolve over the
course of instruction. Do you have the opportunity to ask the teacher?
Here are the safe versions of malloc and free. Also confusing to me!

void *safemalloc(int sz)
{
void *r;
return sz<=0 ? 0 :
(r=malloc(sz)) ? r :
((!!printf("fatal error cannot alocate %d bytes dumping core",sz)
&& (exit(1),0)),NULL);
}
Is this a copy and a paste? "alocate" might be a typographical error
for "allocate". If it's not a copy and a paste, did you re-type the
whole thing by looking at a paper? I'm curious about the original
spacing and indenting format, if you please.

One or more generous authors have kindly offered an online indenter,
available at http://indentcode.net/ That doesn't help very much for a
chain of ternary operators, but might come in handy for you with other
code. There's also 'indent', which might or might not be a command
available in your environment.

I ask about this and mention these formatting tools because if one is
trying to understand code, there might be a visual (or spatial)
challenge which can be alleviated... Maybe not entirely for these
functions.
void safefree(void *p)
{
free(p?p:
(!!printf("fatal error cannot free null pointer dumping core")
&& (exit(1),0),NULL));
}

There appears to be an emphasis on avoiding multiple statements in these
functions. Instead of ';' sequence points, we have ternary conditional
operator ('?:') sequence points and comma operator (',') sequence
points. By avoiding 'if' and restricting statements to declarations and
'return', it might be understood as a means to transition from
mathematics into C, since the rest are operators and function calls
(which are like N-ary operators).

There also appears to be an emphasis on avoiding explicitly identified
local variables wherever possible.

Consider (if you'd like to) an alternative to 'safemalloc':

void *safemalloc(int sz)
{
/* Things we might use. */
int sz_lteq_zero;
void *malloc_ptr; /* Was 'r' */
void *malloc_returns_non_null_ptr;
const char *msg;

/* Things we need #1. */
sz_lteq_zero = sz <= 0;

/* Things we do with things from #1. */
if (sz_lteq_zero)
return 0;

/* Things we need #2. */
malloc_ptr = malloc(sz);
malloc_returns_non_null_ptr = malloc_ptr;

/* Things we do with things from #2. */
if (malloc_returns_non_null_ptr)
return malloc_ptr;

/* Things we need #3. */
msg = "fatal error cannot alocate %d bytes dumping core";

/* Things we do with things from #3. */
return ((!!printf(msg, sz) && (exit(1), 0)), NULL);
}

That example does not attempt to improve the teacher's instructional
'safemalloc' whatsoever, but it attempts to demonstrate how the function
might look using local variables and 'if' statements.

Fun.
 
P

parjit

Seebs said:
Same here, plus it's actually less safe than the standard C one, because
free(NULL) has been well-defined for something over twenty years.

Here is what our course notes say about this:
"NULL pointers are ticking time bombs! Try to manipulate them (eg by
dereferencing them or freeing them) and your program is likely to crash.
Even if it doesn't, if you are manipulating a NULL pointer then something
has gone seriously wrong and you should fix your code."
 
J

Joachim Schmitz

parjit said:
Here is what our course notes say about this:
"NULL pointers are ticking time bombs! Try to manipulate them (eg by
dereferencing them or freeing them) and your program is likely to
crash. Even if it doesn't, if you are manipulating a NULL pointer
then something has gone seriously wrong and you should fix your code."

Then your course notes are wrong free(NULL) is perfectly safe, because the
standard says so.
And in general manipulating a NULL pointer usually is better (and never
worse) than manipulating an invalid pointer.

Bye, Jojo
 
J

Joachim Schmitz

Joachim said:
Then your course notes are
partly

wrong, free(NULL) is perfectly safe,
because the standard says so.
And in general manipulating a NULL pointer usually is better (and
never worse) than manipulating an invalid pointer.

Your program is indeed likely to crash. It is even more likely to crash on a
NULL pointer than on any other invalid pointer, and that's the good thing.
Better crash your program than trashing your data.

Bye, Jojo
 
S

Seebs

I see three alternative statements being discussed.
The first one which you recomend, as being "better"
starts with "I think" and then says something wrong for C89
and very nearly useless for C99.

Yes. (I felt it would be a better example if it were, after all,
incorrect.)
Why is it better to say "I think" before
saying something useless or wrong?

So that readers will be more likely to check your results rather than
assuming that they are known facts. People are astonishingly likely to
accept without verification claims that are made sufficiently confidently.

-s
 
S

Seebs

Here is what our course notes say about this:
"NULL pointers are ticking time bombs! Try to manipulate them (eg by
dereferencing them or freeing them) and your program is likely to crash.
Even if it doesn't, if you are manipulating a NULL pointer then something
has gone seriously wrong and you should fix your code."

I would agree for dereferencing, but not for freeing. The standard
specifically defines free(NULL) as a harmless no-op, and there are sound
reasons to have done so. (In particular, it guarantees that for all x
returned by malloc, free(x) is a valid followup.)

This becomes more useful with large data structures, where peppering
everything with "if(x) free(x);" can seriously clutter the code and
make it harder to see what you're doing.

Basically, it's a style question. Furthermore, let's say we grant the
idea that you should never free a null pointer, because it's a sign that
something has gone seriously wrong.

In that case, the proposed "safefree()" function is DEVASTATINGLY bad,
because it goes out of its way to CONCEAL a bug. It encourages the user
not to make this check, which we've just conceded is an important one.

Finally: The term is "a null pointer". NULL is a constant which meets
the requirements for a null pointer constant. The phrase "a NULL pointer"
is at best a little weird. Consider:
int *p = malloc(-1);
On nearly all systems, v will now be a "null pointer". However, p
is not "NULL". Consider the following line:
double *d = p;
this will not compile, but:
double *d = NULL;
would.

-s
 
B

Barry Schwarz

That is because this code is confusing.

snip comprehensive explanation
Let's convert that to if/else:
        char *safegets(char *buf, int size);
        {
                char *temp1, *temp2;
                if (buf == NULL || size < 1) {
                        return NULL;
                } else if (size == 1) {
                        *buf = '\0';
                        return buf;
                } else if (!(temp1 = fgets(buf, size, stdin))) {
                        return temp1;
                } else if (temp2 = strchr(buf, '\n')) {
                        *temp2 = 0;
                        return temp1;
                } else {
                        return temp1;
                }
        }

Okay, this is still crap.  I would not approve this code in a tech
review but it's getting legible.  Lemme give it some comments:

        /* read at most size characters into buf, resulting in a
         * null-terminated string.  If buf is null or size is not
         * at least 1, returns null.  If fgets() fails, returns
         * null.  Otherwise, returns buf, with the first newline
         * (if any) replaced with a null byte.  Since fgets() in
         * theory stops with the newline, that just trims a trailing
         * newline.
         */

Why "in theory"? Do you know of an implementation where it doesn't in
practice? Does fgets return NULL when it fails only in theory? Does
return exit a function only in theory?

snip rest of explanation
 
B

Barry Schwarz

snip
Here are the safe versions of malloc and free. Also confusing to me!

void *safemalloc(int sz)
{
  void *r;
  return sz<=0 ? 0 :
    (r=malloc(sz)) ? r :
    ((!!printf("fatal error cannot alocate %d bytes dumping core",sz)
    && (exit(1),0)),NULL);

}

void safefree(void *p)
{
   free(p?p:
   (!!printf("fatal error cannot free null pointer dumping core")
   && (exit(1),0),NULL));

As a matter of design philosophy, if I call a function correctly with
valid arguments, I don't want that function to terminate my program
just because it fails due to some external problem. If I don't have a
work-around for the problem, I can terminate the program myself.
General puprose functions should never make that decision for me.
 
S

Seebs

Why "in theory"? Do you know of an implementation where it doesn't in
practice? Does fgets return NULL when it fails only in theory? Does
return exit a function only in theory?

Heh. I think I was glossing over the cases where fgets stops before a
newline, but I certainly didn't explain that well, if that's indeed what
I meant.

-s
 

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
474,083
Messages
2,570,591
Members
47,212
Latest member
RobynWiley

Latest Threads

Top