18

I was searching for a way to find the size of an array in C without using sizeof and I found the following code:

int main ()
{
    int arr[100];
    printf ("%d\n", (&arr)[1] - arr);
    return 0;
}

Can anyone please explain to me how is it working?

6
  • 4
    There is never a reason why you can't use sizeof. Commented Apr 15, 2013 at 15:31
  • It seems that the array, which has 100 elements is actually treated as item 0 of an (unnamed) array. Commented Apr 15, 2013 at 15:32
  • Nice trick, it's also standard compliant. Commented Apr 15, 2013 at 15:45
  • @effeffe: maybe, but see Daniel's comments below. I don't think it is standard compliant, although I can't think of a good reason for it not to work in practice. The subtraction, I mean -- the use of %d is certainly not strictly conforming and in fact would fail on a fairly normal-looking big-endian implementation with a 32 bit int and a 64 bit ptrdiff_t. Commented Apr 15, 2013 at 16:09
  • @SteveJessop actually you're right, it could be not standard compliant, let's follow that discussion there. However, I agree that it should work, but the standard can't let us dereference a pointer that doesn't actually point to an object or a part of it, that makes sense. Commented Apr 15, 2013 at 18:01

6 Answers 6

25

&arr is a pointer to an array of 100 ints.

The [1] means "add the size of the thing that is pointed to", which is an array of 100 ints.

So the difference between (&arr)[1] and arr is 100 ints.

(Note that this trick will only work in places where sizeof would have worked anyway.)

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

1 Comment

[1] doesn't mean "add the size of the thing that is pointed to". It means "add the size of the thing that is pointed to and then dereference the resultant pointer".
13

&arr gives you a pointer to the array. (&arr)[1] is equivalent to *(&arr + 1). &arr + 1 gives you a pointer to the array of 100 ints that follows arr. Dereferencing it with * gives you that array that follows. Since this array is used in an additive expression (-), it decays to the pointer to its first element. The same happens to arr in the expression. So you subtract to pointers, one pointing to the non-existent element right after arr and the other pointing to the first element of arr. This gives you 100.

But it's not working. %d is used for int. Pointer difference returns you ptrdiff_t and not int. You need to use %td for ptrdiff_t. If you lie to printf() about the types of the parameters you're passing to it, you get well-deserved undefined behavior.

EDIT: (&arr)[1] may cause undefined behavior. It's not entirely clear. See the comments below, if interested.

15 Comments

Isn't (&arr)[1] - arr also undefined behaviour?
@DanielFischer C99: Additive operators: For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type. So, it looks like this is OK. I mean the [1] part. And the rest is as usual.
But the last sentence in paragraph 8 of that is "If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated." And (&arr)[1] evaluates the * in *(&arr + 1), if I understand correctly. It's okay if you take the address, of (&arr)[1], or apply sizeof to it, that doesn't evaluate the *, but with -?
@DanielFischer: The standard says that &* is a no-op even if dereferencing would be UB (6.5.3.2/3 in C99). In the same spirit we might expect that to apply with decay-to-pointer in the place of &, but I think you're correct that this is not guaranteed in the standard.
@AlexeyFrunze But we don't have *(&E), we have *(&E + 1).
|
1

Generally (as per visual studio), for an array &arr is same as arr ,which return the starting base address of our function.

(&arr)[0] is nothing but &arr or arr

ex: it will return some address : 1638116

Now, (&arr)[1] means we are started accessing the array out of bounce means next array or next segment of the size of present array(100 ahead).

ex: it will return some address : 1638216

Now, subtracting (&arr)[1] - (&arr)[0]=100

1 Comment

"(&arr)[0] is nothing but &arr or arr" -- arr and &arr have different types when though both point to the same location. The former is of type int* while the latter is of type int(*)[100].
0

&variable gives location of the variable (call it as P)
&variable + 1 gives address of the location next to the variable. (call it as N)

(char*)N-(char*)P gives how many characters are there between N and P. Since each character is 1 byte sized, so the above result gives the number of bytes P and N. (which equals to the size of array in bytes).

Similarly, (char*) (a+1)-(char*)a; gives size of each element of the array in bytes.

So the number of elements in the array = (size of array in bytes)/(size of each element in the array in bytes)

#include<stdio.h>

int main()
{
    int a[100];
    int b = ((char*)(&a+1)-(char*)(&a));
    int c = (char*) (a+1)-(char*)a;
    b = b/c;
    printf("The size of array should be %d",b);
    return 0;

}

Comments

0

int arry[6]={1,2,3,4,5,6} //lets array elements be 6, so... size in byte = (char*)(arry+6)-(char *)(arry)=24;

1 Comment

OP asked to explain how his example is working. You gave another example. That's not an answer to OP's question.
-2
int main ()
{
  int arr[100];
  printf ("%d\n", ((char*)(&arr+1) - (char*)(&arr))/((char*) (arr+1) -(char*) (arr)));
  return 0;
}

2 Comments

While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value.
I'll be happy to upvote your answer if you add some explanation about how your code works. BTW, you should use %ld, not %d.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.