tags:

views:

189

answers:

11

Say we have this piece of C code:

int x[] = {1, 2, 3, 4, 5};

printf("%d", *(x + 1)); //prints 2
printf("%d", *(x + 500)); //prints 7209065 (...?)

As you can see from the second call, it still returns something...but it's garbage.

So I ask, how do you handle such a case in C? ie, how do you know if the returned element is really an element that exists in the array or just garbage ?

+4  A: 

Simply speaking you can't. This is just simply a feature / bug / design of the C and C++ language.

JaredPar
+2  A: 

Array boundaries are not checked at runtime. They are simply chunks of memory with an indication of the type held within. This is a language feature and it decreases the total overhead of your code. Like it or not, it is what it is.

Ed Swangren
+1  A: 

In general, this is why the "smarter" data types were created - things like C++'s STL arrays, which can throw exceptions for index-out-of-bounds errors.

Amber
Note though, STL vectors won't check anything by default (operator[]), unless you are accessing them through `at()` method.
EFraim
+10  A: 

Add another variable that holds the length of the array, and whenever you want to access the array make sure you are within the bounds of the array.

Rob
A: 

Practically, either a 0-terminated array, where you have 0 at the end of an array and restrict yourself to traversing it sequentially, or you pass a variable containing the array's length around with the array and check that before all your array accesses.

An array in C does not know, intrinsically, how long it is, and so you cannot get any behavior that relies on that for free.

John Calsbeek
"restrict yourself to traversing it sequentially" - but that would mean losing O(1) for access, no ?
Andreas Grech
It certainly would, in cases where you need checked O(1) access.
John Calsbeek
A: 

This is also why in most of the (more reliable) C libs that use arrays, you see the size of the array passed as a parameter, e.g., fread() fwrite()

JustJeff
+2  A: 

As everyone has noted, you can't do this due to the nature of C. However, there are tools available that you can use to instrument your code, and perform further checks on memory accessing (for use during the development cycle). Purify is one such tool, and one I found invaluable for identifying such issues.

Brian Agnew
Aside from dynamic tools like Purify, there are also static code analysis tools http://en.wikipedia.org/wiki/Static_code_analysis like Splint.
Liran Orevi
A: 

To elaborate on JaredPar's and Ed's answers:

C arrays are a block of contiguous memory. When you say int x[] = {1, 2, 3, 4, 5}; C allocates enough memory for 5 integers. You're asking for the 500th element, so what you're getting is memory that hasn't been properly allocated to X. It's garbage, and it may change each time you run it.

I agree with Rob. Add a variable with the number of elements in X and just do a for loop through each.

If you want arrays that change length at runtime there are better ways to do that.

Jake
+1  A: 

C does not check array boundaries. The onus is on you to check that access is within bounds by comparing against array length ( sizeof(x)/sizeof(x[0]) ).

nagul
A: 

If you are "lucky" enough, or your index deviation is large enough, then you won't get "garbage" - you will get a segmentation fault. but that's actually a good thing, because it helps you to realize that you are doing something wrong. some tools tell you the exact line in which this has occurred.

Sometimes this depends on the input of the program, meaning a segfault occurs only when some input was inserted (for example if your '500' value was received as an input from the user). (those are slightly more annoying to find and handle)

The most problematic cases, are the ones in which you do get "garbage" and "have no way on knowing it".

On those cases there is really no replacement for writing good code in the first place. But as others suggested, Dynamic and Static analysis tools may help a lot.

Liran Orevi
A: 

In large part it's a mistake to think of C as having an "array" type. The syntax you're using is sugar around pointers. x[y] is really syntactic sugar for *x + sizeof(something) * y (where the "something" is more complicated than I want to get into; in this case something is int).

Remember that C is a mid-level language ... a sort of "portable assembly" and you won't bring unwarranted expectations to the table.

Jim Dennis