Edit: Just to clarify, what you get is ptrdiff_t instead of size_t. So if array size is greater than PTRDIFF_MAX, you get undefined behavior [1].
http://trust-in-soft.com/objects-larger-than-ptrdiff_max-byt...
Software is unreliable enough as it is due to problems beneath our notice. It seems reckless to avoid fixing problems that we do notice. Sure, you could argue that rare problems are rare and that users probably won't notice them --- this attitude is penny-wise and pound-foolish, because you can't meaningfully reason about a system that's only probably correct.
I think the article is well-presented and educational.
I don't think so. Anyone with a solid understanding of C understands pointer arithmetic. I think the article isn't obvious only to those who have a weak understanding of the language.
rather than calling out that pointer arithmetic implicitly relies on 'sizeof' in order to be useful, its treated like some kind of magic. i.e. i don't think it points out the not subtle but rather obvious connection, and instead distracts from it...
>rather than calling out that pointer arithmetic implicitly relies on 'sizeof'
Article:
>arr has the type int , where as &arr has the type int ()[size].
For me this is calling out the implicit use of sizeof by pointing out the type.
There's a reason this meme exists: http://i.imgur.com/Z6pFTjj.jpg
Instead of writing either of these:
size_t length = sizeof array / sizeof array[0];
size_t length = (&array)[1] - array;
Define this macro instead: #define countof( array ) ( sizeof(array) / sizeof((array)[0]) )
Or if you must: #define countof( array ) ( (&(array))[1] - (array) )
And then you can just say: size_t length = countof(array);
Edit: I used to call this macro 'elementsof', but it seems that 'countof' is a more common name for it and is a bit more clear too - so I'm going to run with that name in the future.with a cleaner way to do _countof using a template in C++ 11.
You can also use the template technique to pass a fixed size array to a function, and have the function determine the array size (without needing a 2nd length param, or null terminator element). Similar to strcpy_s(): http://stackoverflow.com/questions/23307268/how-does-strcpy-...
MSVC has a built in _countof: http://stackoverflow.com/questions/4415530/equivalents-to-ms...
While we're talking macros, anyone who reads the g-truc.net article should feel itchy after seeing the countof macro in their example:
#define countof(arr) sizeof(arr) / sizeof(arr[0])
Two problems here:1. The last use of 'arr' doesn't have 'arr' wrapped in parenthesis.
2. The entire expression is not wrapped in parentheses either.
If you write a macro that does any calculation like this, play it safe and put parens around every macro argument and parens around the entire expression too. Otherwise you never know what operator precedence will do to you.
Why?
When reading such code, it means I would have to go and lookup a macro definition. So, there's a clear drawback. What's the benefit that makes it worthwhile?
I mean, you don't go look up the definitions of every function that gets called, every time they are called, right?
But my point with suggesting the macro applies equally to the more traditional sizeof division. I have seen code that divides the two sizeofs every time an array length is needed. I think it's better to put that calculation in a macro so you only do it in one place.
int (*p)[10];
This all is much more interesting in C++, because there, in conjunction with references, this lets you write functions that take arrays as arguments and know their length. Like so: template<size_t N>
void foo(const int (&a)[N]) {
for (size_t i = 0; i < N; ++i)
cout << a[i];
}
int a[10];
foo(a);Same constraints apply (pointer arith).
I am not sure why this method, applied to ordinary arrays, would be preferred to sizeof (), but since we're shedding light here...
EDIT: pointer arith constraints only apply if we compute the difference (end - beg) in the C code. We could also do that in the linker script itself, and I don't recall whether or not C semantics of ptrdiff_t would be preserved in that case. Such preservation doesn't seem very probable to me, so potentially this method might allow to avoid overflows (or to move them much higher) -- to be checked in the 'ld' doc!
C11 6.5.6/8:
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
he doesn't use the * operator on it, he just calculates its position. If he were to access it (ie, use it with *) then that would be breaking the rule
Shows how difficult it is to get a spec right.
So, IMO, you are right, the code in the article is illegal (strictly speaking).
But I think it is likely that most compilers would still allow it, because that clause in the spec essentially exempts the compiler from adding an explicit bounds check.
So if p is a pointer, then p+1 refers to the next element after p, regardless of the size of the pointee. And so (p+1) - p is 1, again regardless of the size of the pointee.
In this case, &arr is a pointer to array, and &arr + 1 would point to the next array following the first one. But we wanted to calculate the number of elements in the array, not the fact that we have one array. So we dereference the pointer, thus getting an array type, which in turns "decays" to a pointer to the first element of the array, which has the right type for counting the elements using pointer arithmetic.
that's the entire mystery opened and closed afaik. sure you can use some obscure notation if you like, but why not just use sizeof?
Basically ptr + integer requires the compiler to determine the sizeof ptr's type.
No. From 6.5.6 Additive operators:
7 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.
8 [...] if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object [...] If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. 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.
So &arr + 2 can overflow, and &arr + 1 cannot be dereferenced, but &arr + 1 shall not overflow and is not undefined behaviour.
Edit: Also now that I think about it, I've written code that relied on that behavior...not sure if I'd heard it before and internalized and forgot it, or just was being foolish.
Quoting http://stackoverflow.com/a/16019052/1470607
Note that this trick will only work in places where `sizeof` would have worked anyway.Unless you're writing a buffer overflow exploit, in which case you need to know exactly what's on the stack and where, this isn't a good way to program.
Update: misread the article; thought he was differencing with the beginning of the next array.
$ cat test.c
#include <stdio.h>
int arr[5];
int main(int argc, char *argv[]) {
printf("%lu, %ld\n", sizeof(arr) / sizeof(*arr), (&arr)[1] - arr);
}
$ gcc test.c && ./a.out
5, 5
Not saying it's "a good way to program" - it's needlessly obfuscated compared to the standard sizeof alternative. But it doesn't rely on anything tricky.I am not sure it is the case here. The code uses only one array, how can it assume the order of arrays?
in c++, a compile-time equivalent to sizeof would be:
template<typename T, size_t N> size_t sz(T(&)[N]) { return N; }For example, the shift operators have higher precedence than bitwise masking (and/or/xor) since this way the expressions setting/clearing ranges of bits won't require parentheses (so increased readability) and the masking constants in them will be the narrowest. Loading a wide immediate value into a register sometimes takes several instructions, so such precedence also brings in the least cost as well (nowadays compilers take care of that to some extent).
But people frequently mess up this aspect, use lots of parens (and ending up with wide masks) saying this rule is not intuitive. It is.
http://stackoverflow.com/questions/671790/how-does-sizeofarr...
I think this is effectively doing the same thing, but in a non-standard way; ie. I think `int n = (&arr)[1] - arr;` is substituted with the actual the number by the compiler the same way sizeof() would be, only noone will know wtf is going on.
Disclaimer: I didn't look at the generated code to confirm; I guess it could even be compiler/runtime dependent.