Passing arrays to a function

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Ectara
    New Member
    • Nov 2009
    • 24

    Passing arrays to a function

    Say I have a couple functions like so:

    Code:
    typedef float vector[3];
    
    void foo(vector t){
    /* Do whatever */
    }
    
    void bar(void){
    vector v;
    foo(v);
    /* Rest of program */
    }
    Would that be treated the same as:


    Code:
    typedef float vector[3];
    
    void foo(float * t){
    /* Do whatever */
    }
    
    void bar(void){
    vector v;
    foo(v);
    /* Rest of program */
    }
    The main thing I'm worried about is if it is pushing 3 temporary float variables on to the stack for the array, rather than passing the array's pointer.
  • Ectara
    New Member
    • Nov 2009
    • 24

    #2
    Did a quick test in GDB, and it appears to pass it as a float pointer. I'll leave this as a reference for others, though it may be implementation dependent.

    Comment

    • Banfa
      Recognized Expert Expert
      • Feb 2006
      • 9067

      #3
      The whole stack is implementation dependent, in fact it is so implementation dependent that there is actually no requirement to have a stack.

      What is implementation dependent is how a given platform passes a compound object, like an array or structure when passed by value. If you pass a pointer then a pointer is what will get passed.

      Comment

      • donbock
        Recognized Expert Top Contributor
        • Mar 2008
        • 2427

        #4
        Following up on Banfa's post ... you should get in the habit of defining your functions to pass pointers to compound types instead of the compound types themselves. You can pass a const pointer if you want to insure the function doesn't change the caller's copy. Likewise, you should get in the habit of defining your functions so they do not return compound types.

        The language allows you to pass and return compound types, and that feature does indeed work, but you don't really know how the underlying implemention accomplishes that. You may end of with especially ineffiicient code or with code that is not thread-safe.

        Comment

        • Ectara
          New Member
          • Nov 2009
          • 24

          #5
          If I pass a pointer to a vector3, I get a pointer to a pointer, and I'm not sure it would be efficient to double dereference. I never return a vector3 in the first place. I was merely wondering if it passed a float pointer to a function rather than allocate/occupy/magically create 3 float values in an array for local use, like it would passing a structure by value. I know how a stack works.

          Comment

          • rstiltskin
            New Member
            • Feb 2010
            • 14

            #6
            I hope you don't mind my jumping in, but I'm puzzled by Banfa and donbock's posts. Should arrays be lumped together with all compound types? In Ectara's example, v is just an array of 3 floats, not a structure. Isn't it true that whenever an arrayname is passed as a function argument it is implicitly converted to a pointer ( although NOT when passed to the sizeof or addressof operators)? Isn't that required by both C and C++ standards, and not implementation-specific?

            Also, if there's any doubt about that, you could pass &v[0] which is certainly a pointer.

            Comment

            • Banfa
              Recognized Expert Expert
              • Feb 2006
              • 9067

              #7
              Hi rstiltskin,

              The confusion here is partly that Don and I were talking theory where as you are talking practically. You can't actually directly pass an array by value and as you say the array name is a pointer to the first element in the array.

              However examine the first code snipet in the first post. It is not actually passing an array, it is passing a type vector which is typedef'd to an array of 3 floats. vector is therefore a compound type that is an array and it could be passed by value.

              The reason you can passs an array by value is there is no syntax to support this. The typedef gets round this by letting you declare an array using the same syntax you would use to declare an int. Therefore the typedef'd type vector, that is an array, can be passed by value.

              Don and my point is that no compound type, typedef'd vector, structure or anything else you can think of should be passed by value or returned by value in C.

              In C++ things are a bit different, compound types are often returned by value, they have to be for objects to work properly, and so passing by value is not quite so frowned upon either. However you should prefer passing by reference were possible over passing by value.


              Ectara

              Double deferencing is not particularly inefficient and not a particularly great overhead over the single dereference of passing an array or a pointer to an array of float. Passing a pointer to a vector has the added benifit of type checking. You know you will always be receiving the right number of floats because the type checking of the compiler ensures it. If your function accepts a pointer to float then it could be passed a pointer to an array of any number of floats including 1 or 2 which would presumably crash your function.

              If you are really worried about the double dereference and the function is an exceptionally complex you could copy the vector into local data first to remove one or both dereferencing steps during the actual calculation.

              Comment

              • donbock
                Recognized Expert Top Contributor
                • Mar 2008
                • 2427

                #8
                Typedefs in C accomplish less than you might think. The typedef name is little more than a synonym for the underlying type and the two can be used interchangeably .

                rstiltkin: I think you're right -- declaring a variable as vector is equivalent to declaring it as an array of 3 floats. In C89, function arguments declared as [fixed-length] arrays are treated as pointers to the first element of the array and the array size is disregarded. (I don't know if C99 changed this; but I doubt it.) This last point about the array size being disregarded means that the compiler will not complain if you pass an array of a different size!

                Consider the definition of the vector type:
                Code:
                typedef float vector[3];
                It seems to me that Ectara intends to define a compound type that consists of exactly three floats -- no more, no less. Unfortunately, this type definition fails to achieve that goal; at least when it comes to passing it as a function argument. The type should be defined as follows to guarantee that all usages, including function arguments, are identical.
                Code:
                typedef struct { float values[3]; } vector;
                or
                Code:
                typedef struct { float x, y, z; } vector;
                Now you truly have a compound type that Banfa and I recommend be passed and returned by reference rather than by value (in C).

                Comment

                • Banfa
                  Recognized Expert Expert
                  • Feb 2006
                  • 9067

                  #9
                  Hey thats not how I thought it worked by after a little impeical experimentation it does appear that with this defined

                  typedef float vector[3];

                  this

                  void foo(vector vec);

                  and this

                  void foo(float vec[]);

                  are equivilent to the extent that they could both appear in the same file without causing an error.

                  So kudos to donbock


                  rstiltskin what this means is that what I should have said (which is what I almost said) is that it is not actually possible to pass an array by value at all but we were sort of thorising that if you could you shouldn't (in C) for the same reasons that you shouldn't pass a structure by value.

                  Comment

                  • rstiltskin
                    New Member
                    • Feb 2010
                    • 14

                    #10
                    Thanks. I have no argument with that. I was just bothered because you seemed to be suggesting that typedef'ing an array changes the way that the compiler treats it -- in effect creating a new type rather than simply a 'nickname'.

                    But I have to say that this
                    ...what this means is that what I should have said (which is what I almost said) is that it is not actually possible to pass an array by value at all but we were sort of thorising that if you could you shouldn't ...
                    is priceless. ;)

                    Comment

                    Working...