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.
  • M Mike Winiberg

    Without wishing to start a major language debate, I think its important to understand that C was designed to be efficient at using the underlying hardware of the machine, and the way things are declared reflects this: char *sz declares a single variable that points to a place in memory, supposedly holding a char value. This pointer (and here's where dragons lie!) can be made to point to anywhere and to anything regardless of its declaration, you are just telling the compiler that at the place where that pointer points, YOU consider there to be a char value (whether it is or not in reality). char sz[1024] says that at the address represented by sz is a reserved block of memory that holds (in theory) 1024 char items. In your code you can (with some severe caveats!) use both variables in the same way and it's up to you to remember and manage whatever you think you are looking at in that location - this is both the beauty and danger of a language like C - it allows you to manipulate things in much the same way as in assembler and with as few restrictions, but it provides no protection against you doing something stupid. However, even the early compilers would detect if you attempted to treat these two variables as exactly equivalent, but would often only warn rather than prevent it, allowing you to create absolute havoc. Much code rot is caused by the developer incorrectly assuming that, by default, either of these variables is initialised (which is why most compilers these days will attempt to put something sensible in newly declared variables to protect the innocent). Before initialisation char *sz may contain a random address and even attempting to look at it might cause a total system crash if it accidentally points into hardware protected memory. With char sz[1024] though you can be sure that doing char x = *sz is safe because sz already holds a valid address and points into memory allocated to your program, what you don't know is what value you will actually get back from that place before the array is initialised. Why have I bored you all with this stuff? Because so many developers these days seem to know absolutely nothing at all about how the hardware they are driving works - that's fine if you are writing in a high-level domain specific language where everything like that is hidden - no help at all if you are writing a device driver for some complex piece of hardware that is integrated into an operating system of some sort.

    W Offline
    W Offline
    W Balboos GHB
    wrote on last edited by
    #32

    You, in your last paragraph, point out my pet peeve with C#; Everything is separated by '.' - it makes things easier and detaches the developer from what the object really is. Value in enum? Member in a class? Namespace? OK - they worked to make all of this (seem to) work together, smoothly, but it also, by shielding the users from reality, fosters and allows the maintenance of a degree of ignorance. Essentially, C# is a dumbed-down version of C++ . Hardly a surprise as the original stated intent of MicroSloth, when they created it, was to wean users away from vb.NET . Probably this type of pseudo-rant "points" to my stogie attitude developed with age. Or that I learned assembler before C . Quick Anecdote: when my brother got his first computer I worked on getting him to master DOS (a while ago!). At first he started but then he stopped: they installed Windows. I asked him how he'll fix anything if there's a problem, without understanding what Windows was running on. His answer? He'll ask me. And so it goes with C# vs C/C++ background developers.

    Ravings en masse^

    "The difference between genius and stupidity is that genius has its limits." - Albert Einstein

    "If you are searching for perfection in others, then you seek disappointment. If you seek perfection in yourself, then you will find failure." - Balboos HaGadol Mar 2010

    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

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

      As I understand it declarations are written as if operators e.g. you would write "name[123]" to access the 123'rd element in the array named "name" so that's how it is declared. Maybe it should be "[123]name".

      H S 2 Replies Last reply
      0
      • B BernardIE5317

        As I understand it declarations are written as if operators e.g. you would write "name[123]" to access the 123'rd element in the array named "name" so that's how it is declared. Maybe it should be "[123]name".

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

        You seem to be talking about accessing the array, not declaring it. I'm talking about declaring it. Edit: Or if you are, then I think get your point? My response would be that pointers aren't declared like pointer operations.

        Real programmers use butterflies

        B 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

          S Offline
          S Offline
          Stuart Dootson
          wrote on last edited by
          #35

          honey the codewitch wrote:

          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 &

          One thing it's *not* is inconsistent - the pointer modifier belongs with the variable, *not* the type. For example, the following fragment declares a pointer to integer variable and an integer variable. ``` int *pa, a; ``` See [this Godbolt](https://godbolt.org/z/xhd8KP)... One option, were you using C++... ``` template using Array = T[N]; template using Ptr = T*; Array test_array; Ptr test_pointer; ```

          Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

          H 1 Reply Last reply
          0
          • B BernardIE5317

            As I understand it declarations are written as if operators e.g. you would write "name[123]" to access the 123'rd element in the array named "name" so that's how it is declared. Maybe it should be "[123]name".

            S Offline
            S Offline
            Stuart Dootson
            wrote on last edited by
            #36

            You could use `123[name]` as an alternative - that matches the original PDP addressing mode syntax better as well, I suspect!

            Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

            1 Reply Last reply
            0
            • S Stuart Dootson

              honey the codewitch wrote:

              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 &

              One thing it's *not* is inconsistent - the pointer modifier belongs with the variable, *not* the type. For example, the following fragment declares a pointer to integer variable and an integer variable. ``` int *pa, a; ``` See [this Godbolt](https://godbolt.org/z/xhd8KP)... One option, were you using C++... ``` template using Array = T[N]; template using Ptr = T*; Array test_array; Ptr test_pointer; ```

              Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

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

              Stuart Dootson wrote:

              One thing it's not is inconsistent - the pointer modifier belongs with the variable, not the type.

              Yet it's a type modifier. A pointer to an int is a different type than an int.

              Real programmers use butterflies

              1 Reply Last reply
              0
              • H honey the codewitch

                You seem to be talking about accessing the array, not declaring it. I'm talking about declaring it. Edit: Or if you are, then I think get your point? My response would be that pointers aren't declared like pointer operations.

                Real programmers use butterflies

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

                They aren't? I would declare a pointer using the rules of operator precedence always starting with the identifier e.g. "char* name" and utilize it as an operator as "*name" so except for the white space and the casting operator "char" which is no longer needed they are the same. Cheerios

                H 1 Reply Last reply
                0
                • B BernardIE5317

                  They aren't? I would declare a pointer using the rules of operator precedence always starting with the identifier e.g. "char* name" and utilize it as an operator as "*name" so except for the white space and the casting operator "char" which is no longer needed they are the same. Cheerios

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

                  I think we're misunderstanding each other. My OP maybe wasn't as clear as it should have been. I've always declared pointers with the * next to the type. You CANNOT declare arrays that way. Hence my complaint.

                  Real programmers use butterflies

                  B 1 Reply Last reply
                  0
                  • H honey the codewitch

                    I think we're misunderstanding each other. My OP maybe wasn't as clear as it should have been. I've always declared pointers with the * next to the type. You CANNOT declare arrays that way. Hence my complaint.

                    Real programmers use butterflies

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

                    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 1 Reply Last reply
                    0
                    • 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
                                          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