Re: would C be easier to read if...



On Apr 3, 1:23 pm, "Bartc" <b...@xxxxxxxxxx> wrote:
"Robert Smith" <some...@xxxxxxxxxxxxx> wrote in message

news:rd5Jj.5608$n8.2434@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx

some of the syntax wasn't overloaded so much...

Was just musing that if pointer de-referencing and pointer-to-type had
seperate syntax (ie use a character other than '*' for one of them) it
would make things much easier to read. You wouldn't get stuff like:

pthread_create(&thread, NULL, (void *(*)(void*))ThreadProc, (void
*)parameter);

I've got more serious problems with understanding C declarations, for
example:

What on earth does (void *(*)(void*)) mean? It's some sort of cast, so the
type is:

void *(*)(void*)

My guess is it's a function returning type void*, and maybe taking a single
parameter of void*, but what about the (*) in the middle?!


That indicates that it's a pointer to a function.

A cast expression is basically a declaration without the identifier;
for example, when you see

(void *(*)(void*))ThreadProc

substitute

void *(*ThreadProc)(void*);

which reads as

ThreadProc -- ThreadProc
*ThreadProc -- is a pointer
(*ThreadProc)() -- to a function
(*ThreadProc)(void *) -- taking a void* parameter
*(*ThreadProc)(void *) -- and returning a pointer
void *(*ThreadProc)(void *) -- to void

And * does apparently seem to change position. Unless I've got these wrong:

int *a a is pointer to int (* on left)
(int *) pointer to int (* on right)
*a dereference pointer to int (* on left again).

In my case a type declaration that reads linearly from left to right would
help tremendously, because that's what I'm familiar with. Just having the
word 'function' in a function declaration would make things so much clearer!

Maybe C's syntax will get easier with use, I don't know, but since I stay
well clear of anything complicated, probably not.


C's declaration syntax follows a "declaration mimics use" paradigm;
IOW, an object or function's declaration should look as much like how
it's referenced in the executable code as possible. This is probably
best explained with some examples.

Let's say we have a regular int identifier named "foo". Here's how it
would be referenced in the code:

foo = blah();
bar = foo;
printf("%d\n", foo);

So, the declaration of "foo" is pretty simple:

int foo;

Now let's pretend "foo" is a pointer to int. Using the same examples
as above:

*foo = blah();
bar = *foo;
printf("%d\n", *foo);

In each case above, we use the dereference operator "*" to get to the
integer value pointed to by foo. So, our declaration of foo is:

int *foo;

Now let's pretend "foo" is an array of pointers to int:

*foo[i] = blah();
bar = *foo[i];
printf("%d\n", *foo[i]);

And the declaration:

int *foo[N];

In the declarations above, "foo", "*foo", and "*foo[N]" are all called
declarators; the declarator introduces the name of the thing being
declared, and provides additional type information. In the
declaration

int *foo[N];

the int-ness of foo is provided by the type specifier "int", while the
pointer-ness and array-ness are provided by the "*" and "[]" in the
declarator. Note that the "*" and "[]" operators are bound to the
identifier, not the type specifier. Cast expressions seem to violate
this rule, but they really don't; again, think of the cast as a
declaration without an identifier, and mentally substitute the thing
being cast for where the identifier would go.

A few more examples:

int (*foo)[N]; // foo is a pointer to an array of int
...
(*foo)[i] = blah();
bar = (*foo)[i];
printf("%d\n", (*foo)[i]);

int (*foo)(void); // foo is a pointer to a function returning int
...
blah = (*foo)(); // can also be written simply as foo();
printf("%d\n", (*foo)());

int (*foo[N])(void); // foo is an N-element array of pointers to
// functions returning int
blah = (*foo[i])();
printf("%d\n", (*foo[i])());

When you see a particularly hairy declaration, like

char *(*(*(*foo)[N])(double bar))[M];

start by finding the leftmost identifier, and then work your way out,
remembering that [] and () bind before * (i.e., *x[] is an array of
pointer, (*x)[] is a pointer to an array, *x() is a function returning
a pointer, and (*x)() is a pointer to a function):

foo -- foo
*foo -- is a pointer
(*foo)[N] -- to an N-element array
*(*foo)[N] -- of pointers
(*(*foo)[N])() -- to functions
(*(*foo)[N])(double bar) -- taking a double
parameter
*(*(*foo)[N])(double bar) -- returning a pointer
(*(*(*foo)[N])(double bar))[M]; -- to an M-element array
*(*(*(*foo)[N])(double bar))[M]; -- of pointers
char *(*(*(*foo)[N])(double bar))[M]; -- to char

Alternately, you could go the other way, and work from the outside
in. Start by substituting everything between the outermost () with X:

char *X[M];

X is an M-element array of pointer to char.

Now we can start decomposing X:

X = (*Y)
char *(*Y)[M];

Y is a pointer to an M-element array of pointer to char

Y = Z(double bar)
char *(*Z(double bar))[M];

Z is a function returning a pointer to an M-element array of pointer
to char

Z = (*G)
char *(*(*G)(double bar))[M]

G is a pointer to a function returning a pointer to an M-element array
of pointer to char

G = H[N]
char *(*(*H[N])(double bar))[M]

H is an array of pointers to functions returning a pointer to an M-
element array of pointer to char

H = (*foo)
char *(*(*(*(*foo)[N])(double bar))[M]

foo is a pointer to an N-element array of pointers to functions
returning a pointer to an M-element array of pointer to char.
.



Relevant Pages

  • Re: const qualifier and VC6.0
    ... > emphasis is on types, while in C the emphasis is on expressions. ... When declaring pointer and reference variables, ... int &p; ... For example, the following declaration ...
    (comp.lang.cpp)
  • Re: how to call a variable without reference in c
    ... fuction with out sending as a argument, pointer and can't declare as ... int a=10; ... Not in his declaration it didn't. ...
    (comp.lang.c)
  • Re: Question regarding prototypes for 0-ary functions.
    ... int fooint x; ... extern int foo(int, ... ... extern int foo(); is not a valid declaration, ... The definition of foo says it takes one parameter, while the declaration ...
    (comp.lang.c)
  • Re: Virtual function and multiple inheritance
    ... virtual int func(); ... class Derived: Foo, Goo { ... Here pF is a pointer to an object with the same memory layout as a Foo and pG is a pointer to an object with the same memory layout as a Goo. ...
    (microsoft.public.vc.language)
  • Re: C# prototype of C: void**
    ... public unsafe void Capture (int width, int height, bytebuffer) ... but I got the error message "A ref or out argument must be an lvalue". ... declaration in the parameter list of Capture allows changing of the ... > have a pointer to a pointer, you need to pass it by ref. ...
    (microsoft.public.dotnet.languages.csharp)