I saw someone doing this to have array index starting at 1 instead of 0 in C.
a = (int *) malloc(sizeof(int)*3) - 1
Is there any risk in this?
I saw someone doing this to have array index starting at 1 instead of 0 in C.
a = (int *) malloc(sizeof(int)*3) - 1
Is there any risk in this?
Theoretical risk : only null pointers and pointers to, into, or right after an object are valid. Other pointers trigger undefined behaviour on use (if they're dangling) or when creating them through pointer arithmetic.
Practical risk : getting pelted by a random code reviewer.
Is there a risk? Sure.
The malloc
call will reserve some space for you starting at address A, but then you set a
to A-4. Since A-4 might store some important stuff, if you forget you're indexing starting at 1 and inadvertently overwrite the value at a[0]
, you might have a bad time.
But more importantly, why? It'll just confuse people reading your code.
I would advise against this blasphemy ;)
There are only two situations in which the Standard allows a pointer value to point to something other than a valid object:
A null
pointer value doesn't point to anything. Null pointers may be copied, and may be compared using the ==
or !=
operators. Use of the additive, subtractive, or relational operators on a null pointer; use of a dereferencing operator will yield Undefined Behavior except in some cases where it does neither requests an actual dereferencing operator nor pointer arithmetic [e.g. sizeof *p
is legal even when p
is null].
For any object, it is possible to have a pointer to that object, or a pointer "one past" that object; adding one to the former will yield the latter, and subtracting one from the latter will yield the former. Use of the ==
or !=
operators on a "one-past" pointer and a pointer to a different object may sometimes report them as equal, even in cases where accesses made using the pointer to the other object would be legitimate and accesses made with the "one-past" pointer would trigger Undefined Behavior.
Your code attempts to generate a pointer which doesn't point to any valid object, and does not fit any of the described behavioral categories. Note that it would be possible and legitimate to create a pointer to an "array" of N elements such that valid subscripts ranged from K-N to K-1, for any K ranging from 0 to N inclusive (given an array of N objects, it's possible to generate a pointer to any of the N objects, or a pointer "one-past" the last one, for a total of N+1 valid pointer values). A pointer just before the first object would not be valid, however.
Three things:
First -- For me it would be bad practice to have pointers that point to addresses that don't really belong to your programme. As soon as you forget that you made an array that begins with 1 you'll have fun time debugging your code (trust me you will forget).
Second -- So you write something like that. Few months later someone else comes along to do something with your code and doesn't notice that little -1 you put there. He is going to have fun time debugging this code. In short, this is breaking the general contract. Everyone expects arrays or pretty much anything with [] to start at 0 and end at "length - 1".
Third -- Because you broke the general contract that array you made won't work with any standard libraries that expect your array to begin with 0. Every time you decide to use any library with your array you will have to remember to increment that pointer that you would pass as a parameter.
With this you would have to do a lot of remembering and thinking and commenting (for anyone else who uses your code). Thinking and remembering should be reserved for creativity not boiler plate code.