C declarations are half backward
-
Does it bother anyone else that you declare a pointer like:
char* sz; // pointer type, pointer declared *with* type
But an array is declared like this:
char sz[1024];// array type, array declared *after* var name
I think it's inconsistent, and I think the array specifier should have been declared with the type since it's essentially a type modifier like * and & Maybe it's just me?
Real programmers use butterflies
It bothers me to no end. Actually what bothers me even more is that every time I mention it, I mostly get replies defending the stupid [Spiral of Death](http://c-faq.com/decl/spiral.anderson.html). It's bad enough that it's bad, but worse that people feel this kind of Stockholm Syndrome towards a type syntax that just doesn't make sense. (in some sense it's not even a type syntax, because it's not just a type, there's a declaration stuck in the middle of it) Anyway I'll show you something even worse, the syntax for returning a function pointer. Let's say you want to return a pointer to a function that takes two ints and returns an int, a function like `int add(int a, int b)` maybe. It would look like this:
int (*getFunc())(int, int) { … }
Unless you use a `typedef` of course (in C# that is essentially mandatory: you must declare a `delegate` with the signature first and then you can use that).
-
It bothers me to no end. Actually what bothers me even more is that every time I mention it, I mostly get replies defending the stupid [Spiral of Death](http://c-faq.com/decl/spiral.anderson.html). It's bad enough that it's bad, but worse that people feel this kind of Stockholm Syndrome towards a type syntax that just doesn't make sense. (in some sense it's not even a type syntax, because it's not just a type, there's a declaration stuck in the middle of it) Anyway I'll show you something even worse, the syntax for returning a function pointer. Let's say you want to return a pointer to a function that takes two ints and returns an int, a function like `int add(int a, int b)` maybe. It would look like this:
int (*getFunc())(int, int) { … }
Unless you use a `typedef` of course (in C# that is essentially mandatory: you must declare a `delegate` with the signature first and then you can use that).
harold aptroot wrote:
but worse that people feel this kind of Stockholm Syndrome towards a type syntax that just doesn't make sense
I think you're the first person on this thread to agree with me. :laugh:
Real programmers use butterflies
-
What has bothered me more is the fact that: int* pa; int *pa; are the same. Had I been Bjorn, I wouldn't have allowed the latter.
The latter may be the better notation since I can declare; int *pa, a; where pa is a pointer to an int and a is an int. If I declare int* pa, a; this is also legal, where pa is still a point to an int and a is an int.
-
Does it bother anyone else that you declare a pointer like:
char* sz; // pointer type, pointer declared *with* type
But an array is declared like this:
char sz[1024];// array type, array declared *after* var name
I think it's inconsistent, and I think the array specifier should have been declared with the type since it's essentially a type modifier like * and & Maybe it's just me?
Real programmers use butterflies
It's hard to believe that of all the replies no one has ever read K&R C. A variable declaration consists of a type and name and possibly a type reference spec such as * or []. Multiple variable declarations may be combined in a single statement (line) if they are the same type. this is why reference specs go with the name
char *sz, sz2[], sz3[1024];
Types and reference specs can also have modifiers which are can get very confusing with multiple declarations combined on a line.
static const char sz4, *sz5, const *sz6;
Add initializers and you will see why it's pretty standard now days to put one declaration per line.
-
It bothers me to no end. Actually what bothers me even more is that every time I mention it, I mostly get replies defending the stupid [Spiral of Death](http://c-faq.com/decl/spiral.anderson.html). It's bad enough that it's bad, but worse that people feel this kind of Stockholm Syndrome towards a type syntax that just doesn't make sense. (in some sense it's not even a type syntax, because it's not just a type, there's a declaration stuck in the middle of it) Anyway I'll show you something even worse, the syntax for returning a function pointer. Let's say you want to return a pointer to a function that takes two ints and returns an int, a function like `int add(int a, int b)` maybe. It would look like this:
int (*getFunc())(int, int) { … }
Unless you use a `typedef` of course (in C# that is essentially mandatory: you must declare a `delegate` with the signature first and then you can use that).
Greetings but I must differ int foobar(int, int) { return 0; } // I merely followed the operator rules of precedence and associativity for: // "f is a pointer to a function which takes two arguments of type int and int and returns an int" // and voila though the return type doesn't seem to be an operator unless perhaps a cast operator int (*f)(int, int) = foobar; // compiles ok int (*getFunc())(int, int) = foobar; // compiles with syntax error // Cheerios
-
It's hard to believe that of all the replies no one has ever read K&R C. A variable declaration consists of a type and name and possibly a type reference spec such as * or []. Multiple variable declarations may be combined in a single statement (line) if they are the same type. this is why reference specs go with the name
char *sz, sz2[], sz3[1024];
Types and reference specs can also have modifiers which are can get very confusing with multiple declarations combined on a line.
static const char sz4, *sz5, const *sz6;
Add initializers and you will see why it's pretty standard now days to put one declaration per line.
Greetings and Kind Regards May I please direct you to my previous post. Cheerios The Lounge[^]
-
Greetings but I must differ int foobar(int, int) { return 0; } // I merely followed the operator rules of precedence and associativity for: // "f is a pointer to a function which takes two arguments of type int and int and returns an int" // and voila though the return type doesn't seem to be an operator unless perhaps a cast operator int (*f)(int, int) = foobar; // compiles ok int (*getFunc())(int, int) = foobar; // compiles with syntax error // Cheerios
-
But that's not what I wrote. I wanted to *return* a function pointer from a function named `getFunc`.
Greetings and Kind Regards Please permit me to demonstrate the following: By merely following the rules of operator precedence and associativity I deduce the same declaration for getFunc as yourself. I thank Harbison & Steele for teaching me this in their fine C text. Why K&R don't do this is difficult to understand. // "getFunc is a function which returns a pointer to a function which takes two int args and returns an int" // getFunc is a function ... getFunc() // ... which returns a pointer ... *getFunc() // ... to a function which takes two int args ... *getFunc()(int, int) (*getFunc())(int, int) // added ()'s because function call (int, int) has higher precedence than indirection * // ... and returns an int int (*getFunc())(int, int) // Voila No Spiral of Death is needed. Best Wishes Cheerios
-
Does it bother anyone else that you declare a pointer like:
char* sz; // pointer type, pointer declared *with* type
But an array is declared like this:
char sz[1024];// array type, array declared *after* var name
I think it's inconsistent, and I think the array specifier should have been declared with the type since it's essentially a type modifier like * and & Maybe it's just me?
Real programmers use butterflies
C declarations are fine. The problem is in C pointer expressions, where two unfortunate changes were made. First, Ritchie (I presume) chose to make * the pointer dereference operator and either chose or had forced upon him by the * choice the need to make it a *left* unary operator. Had he followed Wirth's prior example in Pascal (using p^ to dereference p), then your backwards issue is automatically solved. Why? Because C declarators are based on how the variable is used in an expression. So int *p; has the * first because you use *p in an expression to make use of the pointer. The array dimension come after the variable name: int a[5]; because you use a[index] in an expression to access a member of an array. If the pointer dereference was on the right, then you wouldn't need the quirky -> operator that only exists to cut down on parentheses, where p->member exists only to avoid typing (*p).member. By the way, the declaration should be "char *p;" instead of the awful "char* p;" that revisionists like to type. The * says that p is a pointer, not that "char" is a pointer. To see the difference, try using: int* p1, p2; /* this will NOT declare two integer pointers! */ The correct syntax is: int *p1, *p1; ...since the * says that what's on the right is a pointer. Again, this misunderstanding wouldn't even come up with a right-unary dereference operator. Most of the C language is admirable, particularly as a product of the early '70s, but this (along with allowing the and parts of libraries to become de facto standards) get my votes for Dennis Ritchie's biggest mistakes.
-
The latter may be the better notation since I can declare; int *pa, a; where pa is a pointer to an int and a is an int. If I declare int* pa, a; this is also legal, where pa is still a point to an int and a is an int.
I was just to reply with the same. I always put the * modifier RIGHT in front of the variable. And it makes sense since, "char *" is not really the type. A lot of beginners are confused when something like the following: char* psz, pszHi, pszBye; and they discover pszHi / pszBye are just character variables. Code like the following helps those initiates: char *psz, *pszHi, *pszBye, chA, chB, *pszString3; Just my $0.02.