From: Logan Shaw on
Jens Thoms Toerring wrote:
> Allan Adler <ara(a)nestle.csail.mit.edu> wrote:
>> "user923005" <dcorbit(a)connx.com> writes:
>
>>> On Feb 26, 8:34 am, Allan Adler <a...(a)nestle.csail.mit.edu> wrote:
>>>> Can someone please tell me what is wrong with the following program and
>>>> how to fix it? It is running on a PC running RedHat 7.1 Linux.
>>>> #include <signal.h>
>>>> int err; void (*onintr)(int);
>>>> #define YES 1
>>>> int main()
>>>> {if (signal(SIGINT,SIG_IGN) != SIG_IGN) {signal(SIGINT,onintr);} return 0;}
>>>> void (*onintr)(int){signal(SIGINT, onintr);if (err == YES) exit(1);
>>>> /* exit(err == YES);*/ return;}
>>>> The compiler (gcc 2.96) complains that there is a syntax error before
>>>> the left brace of the body of onintr.
>>> That's because there is a syntax error before the left brace of the
>>> body of onintr.> The signature should be something like:
>>> void onintr(int val)
>
>> Thanks. I was confused by the man page for signal, which gave the
>> declaration:
>> void (*signal(int signum, void (*sighandler)(int)))(int);
>
>> so I just ASSUMED that that meant that the signal handler had to have
>> the type void (*signalhandler)(int).
>
> If you add a semicolon that would define a variable (called
> 'signalhandler') that is a pointer to a function which takes a
> single int argument and returns void. And that's exactly what
> you need to pass as the second argument to signal()

It would precise to say that you don't need to pass a variable.
You need to pass an expression whose type happens to be the same
as the type of the variable you'd get if declared the variable
with "void (*signalhandler)(int);".

That variable declaration isn't the only way to express the type,
which is what's confusing about the C language here. If you have

void myfunc (int y)
{
}

and

void (*myvar) (int);

then the expressions "myfunc" and "myvar" have the same type[1].
That is a little strange considering they look somewhat similar
but somewhat different as well.

Of course, though those two things above create symbols which
have the same type, there are a couple of important differences:
(1) myfunc is a constant, and (2) myfunc is initialized with a
literal value, which is the body of the function.

- Logan
From: Allan Adler on
"user923005" <dcorbit(a)connx.com> writes:

> On Feb 26, 9:57 am, Allan Adler <a...(a)nestle.csail.mit.edu> wrote:
> > Thanks. I was confused by the man page for signal, which gave the
> > declaration:
> > void (*signal(int signum, void (*sighandler)(int)))(int);
> >
> > so I just ASSUMED that that meant that the signal handler had to have
> > the type void (*signalhandler)(int).
>
> You need to understand the difference between a typedef and a function
> prototype. They are not the same thing.
[snip]
> > What method did you have in mind for understanding the compiler warnings
> > and how would it have worked in the present instance?
>
> It appears to me that you are not a C programmer. May I suggest:
> http://en.wikipedia.org/wiki/The_C_Programming_Language_(book)
> I think you are going to have a terrible time of it if you try to
> implement something in a computer language that you do not understand.

I don't know whether you are simply the local misanthrope or whether you
are just very bad at explaining things. Since your comments do contain some
genuine information and don't consist entirely of put downs, I'm going to
give you the benefit of the doubt and assume the latter. There was a
mathematician named Alfred Young who had a similar difficulty. In writing
about Young's work, Turnbull, in a remarkably tactful expression of Young's
disability, wrote (more or less), "[Young's writing] lacks that quality that
enables the reader to grasp the essential point at the right time." Of course,
Young understood what he was writing. Now that Jens has explained, clearly
and patiently, the first point you mentioned, I understand it.
--
Ignorantly,
Allan Adler <a...(a)zurich.csail.mit.edu>
* Disclaimer: I am a guest and *not* a member of the MIT CSAIL. My actions and
* comments do not reflect in any way on MIT. Also, I am nowhere near Boston.
From: Allan Adler on
Thanks very much to you and to Jens for your very clear and patient
explanations. I think I understand it now. Also, I got the program to
compile, even with the original form of the exit statement. Since I
constructed that program from a much larger program, of some vintage,
that I was trying to compile, that cleared away the last obstacle to
getting the larger program to compile. I've been working on this for
a couple of weeks.
--
Ignorantly,
Allan Adler <ara(a)zurich.csail.mit.edu>
* Disclaimer: I am a guest and *not* a member of the MIT CSAIL. My actions and
* comments do not reflect in any way on MIT. Also, I am nowhere near Boston.
From: Arthur J. O'Dwyer on

On Mon, 26 Feb 2007, Allan Adler wrote:
> "user923005" <dcorbit(a)connx.com> writes:
>> On Feb 26, 9:57 am, Allan Adler <a...(a)nestle.csail.mit.edu> wrote:
>>>
>>> so I just ASSUMED that that meant that the signal handler had to have
>>> the type void (*signalhandler)(int).
>>
>> You need to understand the difference between a typedef and a function
>> prototype. They are not the same thing.
> [snip]
>>> What method did you have in mind for understanding the compiler warnings
>>> and how would it have worked in the present instance?
[1]
>> It appears to me that you are not a C programmer. May I suggest:
>> http://en.wikipedia.org/wiki/The_C_Programming_Language_(book)
>> I think you are going to have a terrible time of it if you try to
>> implement something in a computer language that you do not understand.
>
> I don't know whether you are simply the local misanthrope or whether you
> are just very bad at explaining things. Since your comments do contain some
> genuine information and don't consist entirely of put downs, I'm going to
> give you the benefit of the doubt and assume the latter. There was a
> mathematician named Alfred Young who had a similar difficulty. In writing
> about Young's work, Turnbull, in a remarkably tactful expression of Young's
> disability, wrote (more or less), "[Young's writing] lacks that quality that
> enables the reader to grasp the essential point at the right time." Of course,
> Young understood what he was writing. Now that Jens has explained, clearly
> and patiently, the first point you mentioned, I understand it.

Ah, but understanding a proof after being shown it doesn't make you
a mathematician, any more than understanding the source of a bug after
being shown it makes you a C programmer. To "be a programmer", you
at least have to be able to use "programmer tools" (the man pages,
the language reference) to find the bug /yourself/. And to be a
"C programmer", you should be able to find bugs in C programs, especially
when they're as trivial as syntax errors that the compiler warns you
about.

Now, I've seen several of your other posts, and am willing to give
you more of the benefit of the doubt than user923005 was. Not being a
C programmer certainly doesn't make you stupid. But if you're going to
do much programming in C, you should at least recognize that

int (*foo)()
{
/* blah */
}

is a syntax error, not a function definition.

As you wisely remarked, user923005 did have some excellent advice in
there among the "misanthropy". ;) Get K&R; it's a great resource. As for
the difference between int foo() and int (*foo)(), you might find the
following lecture notes useful. Or not. I'm not sure.

http://www.contrib.andrew.cmu.edu/~ajo/free-software/getline/parsing.html

-Arthur

[1] - Re compiler warnings: Compiler diagnostics, for better or worse,
are usually written by experts for experts. If the compiler tells you
"Syntax error after 'int' on line 37; expected identifier", that's often
just a more verbose way of saying "Hey! You! Look at lines 30-37; there's
a syntax error somewhere around there." Sometimes the exact wording is
more helpful, but IMHO it's usually just a tip-off to go look at the
source code in question. When you know the language intimately, and you
know that a *particular line of code* has an error, it's rarely difficult
to find it.
From: Allan Adler on
Arthur J. O'Dwyer" writes:
> As you wisely remarked, user923005 did have some excellent advice in
> there among the "misanthropy". ;) Get K&R; it's a great resource. As for
> the difference between int foo() and int (*foo)(), you might find the
> following lecture notes useful. Or not. I'm not sure.
> http://www.contrib.andrew.cmu.edu/~ajo/free-software/getline/parsing.html

First, I would like to emphasize that I never claimed to be a competent
programmer. I never took a programming course in school and am essentially
self taught. In the last couple of years I have made a lot of progress in
programming, in the sense that I am increasingly able to write programs that
compile and run according to my expectations, and to figure out what is wrong
with them when they don't. Even so, I don't have systematic and comprehensive
knowledge of the computer systems and languages I use. I realize that this
imposes certain limitations on what I can accomplish but that is the way it
has to be, given my other priorities. Meanwhile, I try to learn things as
I perceive the need to do so and I don't normally have time to do it in the
manner and order that professionals do. That results in an odd combination
of things that I do know and things that I don't know. Sometimes that is an
advantage, sometimes not.

I own (the original) K&R and I use it. But I prefer to use ANSI C, so I
rely more often on Harbison and Steele.

Since you think that this web page is so useful, can you please quote the
precise part of the web page that says explicitly that

> int (*foo)() { /* blah */ }

is wrong? Alternatively, can you construct a proof that it is wrong using
sentences on that web page as axioms? I think that will provide some measure
of the aptness of this web page as a reference for the present discussion.

I'd also like to point out that I did realize that there was something
wrong with the declaration I was dealing with. Knowing that it is wrong
and knowing which of the many possible syntactically correct expressions to
put in its place are two entirely different things. My question was aimed
at the latter problem. Your remarks seem to be aimed at the former.

The art of being able to diagnose someone else's misunderstandings and
ignorance and to figure out exactly what they need in order to understand
a particular thing that they want to learn is the art of the educator. It
takes a lot of experience and a lot of patience. In particular, it takes a
willingness to observe and to ask questions before rushing in with
prescriptive advice. I sense from what you write that you do like to
explain things, that you are enthusiastic about the subject that we are
discussing and that you don't entirely know what to do with these tendencies.
Maybe someday you will become a computer science professor, if you aren't
already. But at some point, you will need to learn something fundamental
about teaching, which is that everyone who seeks to learn has his own history,
his own needs, his own abilities and disabilities and his own unique way of
learning and you will have to learn how to be sensitive to these things.
I can't give you any specific advice about that, especially since I don't
know you, but I do wish you luck with it, both for your own sake and for the
sake of your students.
--
Ignorantly,
Allan Adler <ara(a)zurich.csail.mit.edu>
* Disclaimer: I am a guest and *not* a member of the MIT CSAIL. My actions and
* comments do not reflect in any way on MIT. Also, I am nowhere near Boston.