25

In the program below the length of the array ar is correct in main but in temp it shows the length of the pointer to ar which on my computer is 2 (in units of sizeof(int)).

#include <stdio.h>

void temp(int ar[]) // this could also be declared as `int *ar`
{
    printf("%d\n", (int) sizeof(ar)/sizeof(int));
}

int main(void)
{
    int ar[]={1,2,3};
    printf("%d\n", (int) sizeof(ar)/sizeof(int));
    temp(ar);
    return 0;
}

I wanted to know how I should define the function so the length of the array is read correctly in the function.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
makhlaghi
  • 3,856
  • 6
  • 27
  • 34
  • 1
    The best way to probably do it would be to add an extra parameter that takes the size of the array, i.e. `void temp(int *ar, size_t len);` – mfjones Jul 11 '13 at 09:51
  • @Th3Cuber from what I understand he wants the length as the result. – Adrian Jandl Jul 11 '13 at 09:52
  • 3
    Because sizeof operator computer size at `compilation` time so, it can't be dynamic. you have to pass it explicitly. Read here: [sizeof is a compile time operator](http://en.wikipedia.org/wiki/Sizeof#Using_sizeof_with_arrays) – Grijesh Chauhan Jul 11 '13 at 09:58
  • Why don't you want to use strlen() for this purpose? – Ishmeet Jul 11 '13 at 09:59
  • 1
    strlen() only works on strings, not arrays of integers, isn't this correct? – makhlaghi Jul 11 '13 at 10:05
  • 2
    @Ishmeet `strlen` counts the number of chars before a `\0`, not the capacity of the array. – weston Jul 11 '13 at 10:14
  • @weston that was what I meant, we have to use \0 in the array at the last element, then we can determine size using strlen() – Ishmeet Jul 11 '13 at 10:18
  • Sooooooooo many dupeeeeeees! –  Jul 11 '13 at 10:25

7 Answers7

31

There is no 'built-in' way to determine the length inside the function. However you pass arr, sizeof(arr) will always return the pointer size. So the best way is to pass the number of elements as a seperate argument. Alternatively you could have a special value like 0 or -1 that indicates the end (like it is \0 in strings, which are just char []). But then of course the 'logical' array size was sizeof(arr)/sizeof(int) - 1

Ingo Leonhardt
  • 9,435
  • 2
  • 24
  • 33
  • This is an interesting suggestion! I will try to do it like that. In my program the values in the array have to be positive, so I will add a negative value. But then the problem is this: how can I add a negative value in the end of the array before hand and without knowing how many elements it has in it? – makhlaghi Jul 11 '13 at 09:59
  • In your example you would declare `int ar[] = { 1, 2, 3, -1 };`. In a more complex situation you could e.g. initialize your complete array with -1 in a loop before filling it. – Ingo Leonhardt Jul 11 '13 at 10:00
  • 4
    *`'logical' array size was sizeof(arr)/sizeof(int) - 1`* **NO** array size is: `sizeof(arr)/sizeof(int)` , use `-1` for highest index. – Grijesh Chauhan Jul 11 '13 at 10:06
  • 4
    @Grijesh that's why I wrote "'logical'". Think about `strlen()` where '\0' isn't counted either. – Ingo Leonhardt Jul 11 '13 at 10:08
13

Don't use a function, use a macro for this:

//Adapted from K&R, p.135 of edition 2.
#define arrayLength(array) (sizeof((array))/sizeof((array)[0]))

int main(void)
{
    int ar[]={1,2,3};
    printf("%d\n", arrayLength(ar));
    return 0;
}

You still cannot use this macro inside a function like your temp where the array is passed as a parameter for the reasons others have mentioned.

Alternative if you want to pass one data type around is to define a type that has both an array and capacity:

typedef struct
{
  int *values;
  int capacity;
} intArray;

void temp(intArray array)
{
  printf("%d\n", array.capacity);
}

int main(void)
{
    int ar[]= {1, 2, 3};
    intArray arr;
    arr.values = ar;
    arr.capacity = arrayLength(ar);
    temp(arr);
    return 0;
}

This takes longer to set up, but is useful if you find your self passing it around many many functions.

weston
  • 54,145
  • 21
  • 145
  • 203
12

As others have said the obvious solution is to pass the length of array as parameter, also you can store this value at the begin of array

#include <stdio.h>

void temp(int *ar)
{
    printf("%d\n", ar[-1]);
}

int main(void)
{
    int ar[]= {0, 1, 2, 3};
    ar[0] = sizeof(ar) / sizeof(ar[0]) - 1;
    printf("%d\n", ar[0]);
    temp(ar + 1);
    return 0;
}
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
9

When you write size(ar) then you're passing a pointer and not an array.

The size of a pointer and an int is 4 or 8 - depending on ABI (Or, as @H2CO3 mentioned - something completely different), so you're getting sizeof(int *)/sizeof int (4/4=1 for 32-bit machines and 8/4=2 for 64-bit machines), which is 1 or 2 (Or.. something different).

Remember, in C when pass an array as an argument to a function, you're passing a pointer to an array.
If you want to pass the size of the array, you should pass it as a separated argument.

Maroun
  • 94,125
  • 30
  • 188
  • 241
  • Thank you for the explanation. I understand that, I just wanted to see if there is really no way to do it inside the function, without adding to the parameters. – makhlaghi Jul 11 '13 at 10:01
  • @Maroun Maroun I written same answer very first but it doesn't answer hence deleted, Read my comment to the question. – Grijesh Chauhan Jul 11 '13 at 10:03
  • "The size of a pointer and an int is 4 or 8" - or something completely different. This can be explained very nicely without making incorrect assumptions. –  Jul 11 '13 at 10:27
  • @H2CO3 It's enough to say that you can have two different values to clarify my point, however, I'll add this so it'll be better. – Maroun Jul 11 '13 at 10:31
  • 3
    "*you're passing a pointer to an array.*" no quite right. If an array is passed to a function it "decays" to a pointer to its 1st element. By address this is the same as the pointer to the array, by type it definitely isn't. – alk Dec 30 '17 at 17:43
1

I don't think you could do this using a function. It will always return length of the pointer rather than the length of the whole array.

1

You need to wrap the array up into a struct:

#include<stdio.h>

struct foo {int arr[5];};
struct bar {double arr[10];};

void temp(struct foo f, struct bar g)
{
    printf("%d\n",(sizeof f.arr)/(sizeof f.arr[0]));
    printf("%d\n",(sizeof g.arr)/(sizeof g.arr[0]));
}

void main(void)
{
    struct foo tmp1 = {{1,2,3,4,5}};
    struct bar tmp2;
    temp(tmp1,tmp2);

    return;
}
Greg Buchholz
  • 900
  • 4
  • 17
0

Inside the function ar is a pointer so the sizeof operator will return the length of a pointer. The only way to compute it is to make ar global and or change its name. The easiest way to determine the length is size(array_name)/(size_of(int). The other thing you can do is pass this computation into the function.

ojblass
  • 21,146
  • 22
  • 83
  • 132