Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. The Lounge
  3. C declarations are half backward

C declarations are half backward

Scheduled Pinned Locked Moved The Lounge
data-structuresquestion
57 Posts 25 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B BernardIE5317

    Greetings My point is that if you accept the rules of operator precedence and associativity which I am assuming you do than you must accept the rules of declaration since they are identical. Otherwise you must argue against both and insist e.g. that array elements be referenced as "[123]name" or pointer targets as "name*". Or perhaps you would argue that the rules of declaration be different from the rules of operation but that would complicate things. Kind Regards Cheerios

    H Offline
    H Offline
    honey the codewitch
    wrote on last edited by
    #41

    Oh, I get you. I guess using operator precedence on type modifiers kind of threw me, but i can see why you look at it that way. :)

    Real programmers use butterflies

    B 1 Reply Last reply
    0
    • H honey the codewitch

      wait, are you declaring char [2]a backward to illustrate a point? just to be clear literally I'd ask for is a single change from this:

      char sz[100];

      To this

      char[] sz[100];

      Even if it requires extra typing it would be more consistent. Everything else would be the same. And I'd never abuse the preprocessor that way with the exception of using it to help code complicated compile time computations and make writing them easier. Like the Spirit parsing framework.

      Real programmers use butterflies

      K Offline
      K Offline
      Kirk 10389821
      wrote on last edited by
      #42

      Ah, therein lies the dilemma: What does

      char[] a[100], b;

      declare b as? Worse, when I read "a", it says: "a[100]" is an ELEMENT (or pointer) to an array, Because I see it as:

      char []a[100]; // where [] == *
      char *a[100];

      and

      char[] a(100); // would make more sense, to NOT confuse the symbology to me

      The * modifier and the [] modifiers are applied to the variable, not the type. hence

      char *a,**b,c[100],d; // are all fine

      // And yes the [2]a was just "putting it in front, as requested" But I feel we must "adapt" to nuances of every language. I primarily code in Delphi (Pascal based) for the last 20+ years... So I am having to THINK HARDER about C and C# syntax. That adaptation in C is pretty low, and coding standards would say the Decoration stays with the variable, not the type! That rectifies about 80% of it to me. Proof:

      char* a,b,c; // Does NOT declare 3 variables of the same type!
      char *a,b,c; // Therefore is the proper notation

      IMO...

      H 1 Reply Last reply
      0
      • K Kirk 10389821

        Ah, therein lies the dilemma: What does

        char[] a[100], b;

        declare b as? Worse, when I read "a", it says: "a[100]" is an ELEMENT (or pointer) to an array, Because I see it as:

        char []a[100]; // where [] == *
        char *a[100];

        and

        char[] a(100); // would make more sense, to NOT confuse the symbology to me

        The * modifier and the [] modifiers are applied to the variable, not the type. hence

        char *a,**b,c[100],d; // are all fine

        // And yes the [2]a was just "putting it in front, as requested" But I feel we must "adapt" to nuances of every language. I primarily code in Delphi (Pascal based) for the last 20+ years... So I am having to THINK HARDER about C and C# syntax. That adaptation in C is pretty low, and coding standards would say the Decoration stays with the variable, not the type! That rectifies about 80% of it to me. Proof:

        char* a,b,c; // Does NOT declare 3 variables of the same type!
        char *a,b,c; // Therefore is the proper notation

        IMO...

        H Offline
        H Offline
        honey the codewitch
        wrote on last edited by
        #43

        You make a good point. At which my response is I don't like that C puts the type modifiers with the variable in general. C# doesn't, and i appreciate it for that, but I guess I've been spoiled as this last year i was doing mostly C# stuff.

        Real programmers use butterflies

        1 Reply Last reply
        0
        • H honey the codewitch

          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

          U Offline
          U Offline
          User 13269747
          wrote on last edited by
          #44

          Quote:

          Does it bother anyone else that you declare a pointer like:

          char* sz; // pointer type, pointer declared *with* type

          It only looks odd if you use it like that. If you use it like the way it was meant to be used:

          char *sz;

          It makes sense. The way you write it is not consistent and lends itself to errors.

          char* szA, szB, szC; // Not what you intended, and even if you did intend that
          // the **reader** isn't sure you intended to do that!

          char *szD, *szE, *szF; // Anyone reading this knows exactly what was intended.

          Putting the "*" next to the typename is logically inconsistent - you still have to put the "*" in the correct place for other pointer types:

          void (*fptr) (void); // See? The "*" 'binds' to the variable, not the type.

          So instead of doing it one way for some variables and the correct way for others, just do it the correct way for all.

          H 1 Reply Last reply
          0
          • U User 13269747

            Quote:

            Does it bother anyone else that you declare a pointer like:

            char* sz; // pointer type, pointer declared *with* type

            It only looks odd if you use it like that. If you use it like the way it was meant to be used:

            char *sz;

            It makes sense. The way you write it is not consistent and lends itself to errors.

            char* szA, szB, szC; // Not what you intended, and even if you did intend that
            // the **reader** isn't sure you intended to do that!

            char *szD, *szE, *szF; // Anyone reading this knows exactly what was intended.

            Putting the "*" next to the typename is logically inconsistent - you still have to put the "*" in the correct place for other pointer types:

            void (*fptr) (void); // See? The "*" 'binds' to the variable, not the type.

            So instead of doing it one way for some variables and the correct way for others, just do it the correct way for all.

            H Offline
            H Offline
            honey the codewitch
            wrote on last edited by
            #45

            I suppose then that I do not like that type modifiers are not declared with the type.

            Real programmers use butterflies

            U 1 Reply Last reply
            0
            • H honey the codewitch

              Oh, I get you. I guess using operator precedence on type modifiers kind of threw me, but i can see why you look at it that way. :)

              Real programmers use butterflies

              B Offline
              B Offline
              BernardIE5317
              wrote on last edited by
              #46

              Greetings and Kind Regards Just in passing I wish to mention in case you do not already know about it is that the C text by Harbison & Steele is what the K&R text wished it was. H&S is a beautiful text and is where I learned that declarations and operations follow the same rules. Why K&R didn't explain this is as simply is difficult to understand. Best Wishes Cheerios

              1 Reply Last reply
              0
              • H honey the codewitch

                I suppose then that I do not like that type modifiers are not declared with the type.

                Real programmers use butterflies

                U Offline
                U Offline
                User 13269747
                wrote on last edited by
                #47

                Quote:

                I suppose then that I do not like that type modifiers are not declared with the type.

                Pointers aren't type modifiers. You can tell by the way that actual type modifiers can be placed in any order ("short int" and "int short") while the pointer notation can only go before the variable name.

                short int si1; // Compiles
                int short si2; // Compiles
                short int *psi3; // Compiles
                *short int psi4; // Error, won't compile.

                If you do not associate the '*' with the variable name, then everything looks very confusing and arbitrary and some things that should work won't. If you associate the '*' with the variable name then everything is logical and can be worked out - any "*symbol" means that symbol is a pointer to something, so things like this can be worked out:

                const char *varname[100];

                You cannot logically infer what that means if you think that the "*" is part of the typename. If the "*" is part of the type, that would mean that the pointer can not be changed. In reality, it is the individual chars that cannot be changed, while each of the pointers in the array can be changed. There's a lot of misunderstanding that will happen when "typename* varname" is used in place of "typename *varname". A compiler won't catch all of it.

                1 Reply Last reply
                0
                • H honey the codewitch

                  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

                  L Offline
                  L Offline
                  Lost User
                  wrote on last edited by
                  #48

                  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).

                  H B 2 Replies Last reply
                  0
                  • L Lost User

                    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).

                    H Offline
                    H Offline
                    honey the codewitch
                    wrote on last edited by
                    #49

                    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

                    1 Reply Last reply
                    0
                    • S swampwiz

                      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.

                      J Offline
                      J Offline
                      James Lonero
                      wrote on last edited by
                      #50

                      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.

                      J 1 Reply Last reply
                      0
                      • H honey the codewitch

                        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

                        J Offline
                        J Offline
                        Julie777
                        wrote on last edited by
                        #51

                        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.

                        B 1 Reply Last reply
                        0
                        • L Lost User

                          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).

                          B Offline
                          B Offline
                          BernardIE5317
                          wrote on last edited by
                          #52

                          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

                          L 1 Reply Last reply
                          0
                          • J Julie777

                            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.

                            B Offline
                            B Offline
                            BernardIE5317
                            wrote on last edited by
                            #53

                            Greetings and Kind Regards May I please direct you to my previous post. Cheerios The Lounge[^]

                            1 Reply Last reply
                            0
                            • B BernardIE5317

                              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

                              L Offline
                              L Offline
                              Lost User
                              wrote on last edited by
                              #54

                              But that's not what I wrote. I wanted to *return* a function pointer from a function named `getFunc`.

                              B 1 Reply Last reply
                              0
                              • L Lost User

                                But that's not what I wrote. I wanted to *return* a function pointer from a function named `getFunc`.

                                B Offline
                                B Offline
                                BernardIE5317
                                wrote on last edited by
                                #55

                                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

                                1 Reply Last reply
                                0
                                • H honey the codewitch

                                  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

                                  M Offline
                                  M Offline
                                  mike codeproject
                                  wrote on last edited by
                                  #56

                                  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.

                                  1 Reply Last reply
                                  0
                                  • J James Lonero

                                    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.

                                    J Offline
                                    J Offline
                                    Jeff Clausius SG
                                    wrote on last edited by
                                    #57

                                    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.

                                    1 Reply Last reply
                                    0
                                    Reply
                                    • Reply as topic
                                    Log in to reply
                                    • Oldest to Newest
                                    • Newest to Oldest
                                    • Most Votes


                                    • Login

                                    • Don't have an account? Register

                                    • Login or register to search.
                                    • First post
                                      Last post
                                    0
                                    • Categories
                                    • Recent
                                    • Tags
                                    • Popular
                                    • World
                                    • Users
                                    • Groups