1

In C, I have to pass an array to a function in a single variable, and without knowing what the size the array will be before the program runs. The on-paper solution is to have an extra element to the array where you'll store the array's size (I think this is called a "sentinel value"). Ok, but I'm having problems implementing this.

Passing array[] as a function argument doesn't seem to work. I suppose I can send a pointer to the first element, but how do I then access the rest of the array?

1
  • 2
    What is the problem with passing array as an argument? Commented Apr 22, 2014 at 1:05

3 Answers 3

2

In C, an array decays to a pointer to its first element in most contexts:

6.3.2.1 Lvalues, arrays, and function designators

[...] Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

That is useful, because array indexing a[i], is defined using pointer arithmetic: *(a+i).
So, you can use the same operations on the pointer as on the array.
Still, there is one downside to this consistency: You cannot pass an array by value without wrapping it in a struct.

Next, a sentinel is an invalid value of the element type used as a stop marker, like for strings the 0 and for pointers mostly NULL.
What you actually described was a counted array, having the length prepended at index ((size_t*)a)[-1] or some such.

Sign up to request clarification or add additional context in comments.

2 Comments

Can you please explain or suggest a link about the exceptions like sizeof? Thanks.
The C standard (ISO/IEC 9899:2011) covers the exceptions in §6.5.3.4 The sizeof and _Alignof operators: When applied to an operand that has array type, the result [of sizeof] is the total number of bytes in the array.103) and footnote 103 says: When applied to a parameter declared to have array or function type, the sizeof operator yields the size of the adjusted (pointer) type (see 6.9.1). Similarly, it says: When applied to an array type, the result [of _Alignof] is the alignment requirement of the element type.
2

The choice of the sentinel value depends on the type of data the array stores. For anything involving a pointer, use NULL, and NAN for floating points, e.g.:

char *strings[] = {"foo", "bar", "baz", NULL};
double doubles[] = {1.0, 2.4, 6.5, NAN};

Now checking where the array ends amounts to walking along the array until you find the sentinel:

#include <stddef.h>  // for NULL

size_t count_strings(char **strings) {
    size_t num_strings = 0;
    while ((*strings)++ != NULL) {
        num_strings++;
    }
    return num_strings;
}


#include <math.h>    // for NAN and isnan(…)

size_t count_doubles(double *doubles) {
    ...
    while (!isnan(*doubles++)) {
        ...
    }
}

Finding a sentinel is more difficult for some data types (say, int), but you can then choose a conventional value.

2 Comments

The doubles example has an extra level of indirection that it shouldn't
@MattMcNabb: Thanks for the constructive feedback.
-1

You iterate over the array whose address is passed in as the first parameter, and check the range by the array length that's passed in as the second parameter.

// Or, void f(int *a, int size) as the array decays
// to a pointer when passed into this function
void f(int a[], int size)
{
   // It's your own responsibility to make sure you
   // don't access the out-of-range elements.
   for (int i = 0; i < size; ++i)
   {
      printf ("%d\n", a[i]);
   }
}

// use of f()
int a[10];
// or f(&a[0], sizeof(a) / sizeof(a[0]))
f(a, sizeof(a) / sizeof(a[0]));

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.