Thread: question about sorting function arguments

  1. #1
    Registered User
    Join Date
    Sep 2015
    Posts
    9

    question about sorting function arguments

    For my assignment the professor gave an example of a sorting function as:

    Code:
     void static mysort(int (&x)[ASIZE] );

    I'm confused as to what int (&x)[ASIZE] would mean as arguments. ASIZE is suppose to be the max size of our array that we pass into to be sorted. The function is a member of a class that has all the functions with the same name (overloading?). He also implied we can add more arguments to the function as needed.

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    ASIZE is not just the max size, it is THE size of the array that needs to be passed in. You should find with some experimenting that other sizes result in compiler errors. It's one reason why I don't like this technique...

    The overloads are likely just variations on the type of array.

    Basically the only way to call it successfully is to declare an array of ASIZE length and pass in that array:

    Code:
    int array[ASIZE] = { 1,2,3,6,5,4 };
    sort(array);

  3. #3
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    It's declaring x as a reference to an int array of size ASIZE.
    I can discern no advantage, however, since ASIZE is a constant.
    The usual way to do it (in C) is like this:
    Code:
    void mysort(int x[], int size); // or size_t size
    In C++ a std::vector or std::array is preferred.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    It is the way for you to have the array itself passed by reference, and in so doing avoid the conversion of the array into a pointer to its first element. Observe:
    Code:
    #include <iostream>
    
    #define ASIZE 10
    
    static void mysort(int (&x)[ASIZE]);
    
    int main()
    {
        int a[ASIZE];
        mysort(a);
    
        int b[ASIZE + 1];
        mysort(b);
    }
    
    static void mysort(int (&x)[ASIZE])
    {
        std::cout << sizeof(int*) << " versus " << sizeof(x) << std::endl;
    }
    You will see that while mysort(a) is fine since you can pass an array of ASIZE int elements by reference to a parameter that is a reference to an array of ASIZE int elements, mysort(b) results in a compile error since an array of ASIZE + 1 int elements does not match in type. Now, remove the mysort(b) call, compile and run the program. You will most likely observe that sizeof(x) is not equal to sizeof(int*), whereas if mysort were:
    Code:
    static void mysort(int x[ASIZE]);
    It would be equal since x would be a pointer to int.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Sep 2015
    Posts
    9
    Thanks for your reply, helped a lot. And everyone else as well!

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by algorism View Post
    I can discern no advantage, however, since ASIZE is a constant.
    I can. It allows you to enforce, at compile time, that the array is of exactly ASIZE elements. Any less and any more will result in a compile error.

    The usual way to do it (in C) is like this:
    Code:
    void mysort(int x[], int size); // or size_t size
    If you do it this way, you put the responsibility on the caller to pass the correct size. If the size is incorrect, bad things™ will happen. If you use good guidelines and code review, chances that you will pass the incorrect size will be diminished, but there's no guarantee that you pass the correct size. The above guarantees that it's exactly ASIZE elements. All. the. time. Unless there's a compiler bug.

    In C++ a std::vector or std::array is preferred.
    This is still good advice, though, and would be the preferred approach.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Guest
    Guest
    Is there logic to this syntax (as with function pointers), that follows from the general rules of variable declaration, or is it just one of those cases where some solution was needed? It doesn't seem very intuitive.
    Code:
    // these would seem less weird
    void mysort(int x[100]&);
    void mysort(int[100]& x);
    Last edited by Guest; 05-07-2016 at 03:08 PM.

  8. #8
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by Guest View Post
    Is there logic to this syntax (as with function pointers), that follows from the general rules of variable declaration, or is it just one of those cases where some solution was needed? It doesn't seem very intuitive.
    Code:
    // these would seem less weird
    void mysort(int x[100]&);
    void mysort(int[100]& x);
    The logic is identical to that of function pointers. The array indexing operator has higher precedence (same as the function application operator), so the parentheses are needed around the (&x) part. Your second example syntax would be better but since C++ is meant to be as compatible as possible with C, the syntax can't be cleaned up.

    Does anyone see any advantages of this reference-to-C-array approach? It has the disadvantage of requiring a fixed-sized array. I don't see any advantages.

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by algorism View Post
    Does anyone see any advantages of this reference-to-C-array approach? It has the disadvantage of requiring a fixed-sized array. I don't see any advantages.
    I mentioned some advantages in post #6.
    If you want to accept arrays of any size, you can make the size a template parameter, which is way superior to the C approach.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by Elysia View Post
    If you do it this way, you put the responsibility on the caller to pass the correct size. If the size is incorrect, bad things™ will happen. If you use good guidelines and code review, chances that you will pass the incorrect size will be diminished, but there's no guarantee that you pass the correct size. The above guarantees that it's exactly ASIZE elements. All. the. time. Unless there's a compiler bug.
    This can be more unhelpful than the debugging it tries to prevent.

    Because what would be nice is just passing in an array and getting the size correct no matter what. But with passing arrays by reference if the chosen constant is too big or too small, you have the same problem. It might be right for some arrays and wrong for others.

    I find you have to write code around passing arrays by reference in order to get it to work correctly. I find that very stupid.

  11. #11
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by whiteflags View Post
    This can be more unhelpful than the debugging it tries to prevent.

    Because what would be nice is just passing in an array and getting the size correct no matter what. But with passing arrays by reference if the chosen constant is too big or too small, you have the same problem. It might be right for some arrays and wrong for others.

    I find you have to write code around passing arrays by reference in order to get it to work correctly. I find that very stupid.
    It may not be useful for an algorithm like sort, because you're better off with a more generic sort algorithm. But if you only ever need to use a particular size array, then this technique works fine, although it's still inferior to using std::array. For example, you might have a game board that is a fixed size array. Usually this would be a 2d array, but the principles are the same either way. In this case you could use this technique to pass around game boards, which would fail to compile if you ever pass it a game board with the wrong dimensions.

    There is a third option that is often preferable however: passing in a class that contains the array in question. This is more type safe, because it incorporates the semantic meaning, such as that of being a game board, in the type.


    In this example of demonstration sorting the technique is fine, IMO, since it allows the beginner-programmer implementer to ignore the complexities of variable size arrays, and focus on sorting. It is of course, an academic example.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  12. #12
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by Elysia View Post
    I mentioned some advantages in post #6.
    If you want to accept arrays of any size, you can make the size a template parameter, which is way superior to the C approach.
    I'm sorry. I don't know how I missed your previous post.

    So the advantage is compile-time checking that the fixed-sized C-style array is correctly sized, and that the user of the function doesn't need to pass in the size. It's not necessarily superior to the C code since they are solving different problems, with the C version being variable-sized, but clearly that's not what is being asked for here. Still, this is C++ so, as you say, a C++ solution is better, presumably involving array or vector.

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    They don't solve the same problem, no, but if you make the size a template arguments, it becomes a superior way of doing it. There's no way to get the size wrong.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    What if we just implemented this in terms of an instantiation of the iterator_traits class instead?

  15. #15
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    The parameter could be a reference to a row in a matrix, although it would need a cast to be used this way.

    Code:
    #define NROW 2
    #define NCOL 3
    
    void foo(int (&x)[NCOL])
    {
        ((int (*)[NCOL])x)[1][2] = 1;
    }
    
    int main()
    {
    static int m[NROW][NCOL];
        foo(m[0]);
        return 0;
    }
    Last edited by rcgldr; 05-08-2016 at 05:08 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 7
    Last Post: 11-21-2008, 04:27 PM
  2. Yet another function arguments question
    By audinue in forum C Programming
    Replies: 3
    Last Post: 10-20-2008, 05:09 AM
  3. Replies: 9
    Last Post: 01-02-2007, 04:22 PM
  4. Easy question about arguments in a function
    By pond-person in forum C++ Programming
    Replies: 5
    Last Post: 12-12-2002, 10:36 PM
  5. Replies: 2
    Last Post: 03-07-2002, 10:14 AM

Tags for this Thread