1

A normal way to get the length of an array is to use sizeof(a)/sizeof(a[0]), for example:

for(j = 0; j < sizeof(a)/sizeof(a[0]); j++ )
    do_something_with(a[j]);

however there's a risk if a is just a pointer:

int *a = calloc(1, sizeof(int));

for(j = 0; j = sizeof(a)/sizeof(a[0]); j++ )
    do_something_with(a[j]);

then one might get this to loop two times which is bad (if you're lucky sizeof(int*) and sizeof(int) is the same and it will only be one round).

Is there a way to create this macro such that it fails if a is not of array type? The reason it need to fail is that if a is not an array, but a pointer there's no safe way to determine the length of the vector (and certainly sizeof(a)/sizeof(a[0]) might result in a out of bound access).

skyking
  • 13,817
  • 1
  • 35
  • 57
  • 4
    @LPs Doesn't look like a duplicate. This question wants something that fails [explicitely] when `a` is a pointer rather than an array. – Viktor Dahl Feb 22 '16 at 10:43
  • 1
    Note: `for(j = 0; j = sizeof(a)/sizeof(a[0]); j++ )` should be `for(j = 0; j < sizeof(a)/sizeof(a[0]); j++ )` – Spikatrix Feb 22 '16 at 10:46
  • 6
    The question is really "Why on earth would you be worried about it?" You can only use `sizeof a/sizeof *a` *in the scope where `a` is declared.* It seem hard to imagine that a programer wouldn't know if he declared an array or pointer in a single scope before attempting a `sizeof a/sizeof *a`. (I'm just saying....) – David C. Rankin Feb 22 '16 at 10:46
  • 1
    @DavidC.Rankin to avoid bugs. **Humans are not compilers** and can easily miss if a variable is a pointer and not an array. Such a macro is useful and the linux kernel defines one. – bolov Feb 22 '16 at 10:49
  • @DavidC.Rankin Sometimes even programmers makes mistaeks. – skyking Feb 22 '16 at 10:49
  • If you do not want to have such problems juz wrap your array with structure that contains this array and it's lenght. – Gaskoin Feb 22 '16 at 10:50
  • Solution is to program defensively, and use separate size variable/constant. – user694733 Feb 22 '16 at 10:50
  • It seem to be a duplicate of "Array-size macro that rejects pointers", but certainly not to "How to find the 'sizeof'(a pointer pointing to an array)?". It would be appropriate to remove the later from the list of duplicates... – skyking Feb 22 '16 at 10:51
  • @skyking There was a first vote as duplicate to that link. Don't worry about it. The system will take care of if if there are no other votes for that link. I think. – bolov Feb 22 '16 at 10:52
  • I think gcc and clang give warnings for this case. It would be so very, very unlikely that given say int* p, you would intentionally evaluate sizeof (p) / sizeof (*p). They also give warnings for things like p += sizeof (x) (beginner's mistake) if p is not a pointer to char. – gnasher729 Feb 22 '16 at 10:54
  • Good question. I use the same method with `sizeof` and pay attention each time for pointer risk. Maybe this can protect: `ASSERT( sizeof a > sizeof (INT_PTR) );` – i486 Feb 22 '16 at 10:55
  • @gnasher729 if you have a (badly written) function `int foo(int v[100])` then `v` looks like a legit array to someone that is not experienced. Compile time checks are always useful. – bolov Feb 22 '16 at 10:57
  • @i486: Only on Windows compilers because nobody else has ASSERT or INT_PTR. And it doesn't work for short a{} = {1,2,3,4}; – gnasher729 Feb 22 '16 at 10:58
  • @gnasher729 Yes, the method will give false assert on small arrays. But `ASSERT` and `INT_PTR` are not problem - can be replaced with `assert` and `sizeof (int *)` for all platforms. – i486 Feb 22 '16 at 10:59
  • What's wrong with `a = a`, which takes advantage of illiegel array assignment? – nalzok Feb 22 '16 at 11:53

0 Answers0