-2

I am using a c++ integer array (int *). I have number sets generated and placed into this array, such as 1, 0, 3, 4, 5. The array is allotted 16 characters by this method

int *arr = (int *)malloc(16). 

I need to be able to loop through this array and use each number and tell how many numbers are in the array. To loop through each element in the array, I have tried two methods:

for(int i=0;i<sizeof(arr);i++) and for(int i=0;arr[i]!='\0';i++). 

The problem with the first method is that sizeof returns 16, because thats how much space I allotted for that array. The second method is successful unless there is a 0 in the sequence. How should I go about looping through each element in the array without getting stuck on 0 or looping through all 16 slots?

Ashish
  • 1,121
  • 2
  • 15
  • 25
jamespick
  • 1,974
  • 3
  • 23
  • 45
  • 1
    `int*` is not an array. It is a pointer. `The problem with the first method is that sizeof returns 16` No it doesn't. – Lightness Races in Orbit Jan 03 '14 at 21:51
  • What problem are you actually trying to solve? Instantiating an array of `int` and looping over it really isn't that complicated. – juanchopanza Jan 03 '14 at 21:53
  • @LightnessRacesinOrbit how? That creates a usable array for me. Thats what I though at first too but it created an array for me. That method that I said above seemed to work the same way as int arr[16]; – jamespick Jan 03 '14 at 21:53
  • 3
    The problem is that you didn't study pointers and arrays thoroughly enough, and/or you didn't think about the problem using your programming knowledge, logic and common sense. You will need to read a good beginner C++ book or tutorial, especially its chapter(s) that cover(s) pointers and arrays. –  Jan 03 '14 at 21:53
  • Are you sure `sizeof(arr)` is giving `16`? I'd think it would be 4 or 8, usually, on account of `arr` being a pointer. Also, you're confusing "integer slots" with bytes -- 16 bytes only gives you four integers' worth of slots, assuming 4-byte integers. – Cameron Jan 03 '14 at 21:54
  • @InsertNameHere: What do you mean "how?" `int*` is a pointer, I just told you. You didn't create any array but simply allocated a block of contiguous `int`s in dynamic memory. An array is like `int arr[16]`. – Lightness Races in Orbit Jan 03 '14 at 21:59

4 Answers4

7

Since you've used dynamic allocation for this "array" (block of memory), the dimension of the array is not known to the type system. That means you cannot use sizeof(arr). All you've done there is find the size of your int* (a pointer).

And, as you've discovered, trying to null-terminate this array is completely silly because 0 is a perfectly valid, sane integer value.

What you should do is one of the following:

Option 1

const unsigned int LENGTH = 16;
int* ptr = new int[LENGTH];     // (malloc is an ancient approach from C)

for (unsigned int i = 0; i < LENGTH; i++) {
   // ...
}

delete[] ptr;

// here, I've remembered the block's size myself

Option 2

std::vector<int> vec(16);
for (auto myInt : vec) {
   // ...
}

// here, the wrapper called "vector" knows its own size

Option 2a

If you just picked 16 arbitrarily to provide a maximum upper bound, and you don't always need 16 elements:

std::vector<int> vec;   // this grows as needed
vec.push_back(1);
vec.push_back(0);
vec.push_back(3);

for (auto myInt : vec) {
   // ...
}

Option 3

If the value 16 doesn't rely on user input or other runtime data, leave out the dynamic allocation:

std::array<int, 16> arr;
for (auto myInt : arr) {
   // ...
}

Or, to go old-school:

int arr[16];
for (auto myInt : arr) {
   // ...
}

Conclusion

It's hard to tell what you're trying to do, but I think you are trying to have a bunch of array elements, not all of which may be "used" at any one time, and somehow mark the "un-used" ones. In this case, you want to abandon that old-fashioned logic, and use option 2a above.

Bootnote

I've used some C++11 constructs here, namely std::array and the ranged-for loop. Replace the loops with more conventional equivalents as you required.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • I don't want to loop through all the elements in the array, only the ones that aren't null. Is there a way I can stop at the null ones? I want to get how many elements aren't null. – jamespick Jan 03 '14 at 21:56
  • 1
    @InsertNameHere: You have to look through them all otherwise you won't know which are "null". You need to define what you mean by "null". I think you are coming from a Java background where objects can either have a value or "be null", but that is not the case here. – Lightness Races in Orbit Jan 03 '14 at 21:57
  • haha no actually I do mainly Objective C, but that is the case there as well as Java. What I mean by null is that i haven't set a value to it yet. – jamespick Jan 03 '14 at 21:58
  • @InsertNameHere: Then you are trying to fill in array elements to a maximum quantity, and somehow "mark" the un-used ones. Instead of this, use my **option 2a** above which simply expands your array as necessary, leaving no "un-used" elements at all. Your only other alternative is to pick a sentinel value (say, `-1`) and stick with it. – Lightness Races in Orbit Jan 03 '14 at 22:00
  • Sorry, what exactly does a vector do? I don't quite understand your code, for I have never used vectors before. Could you explain please? @LighnessRacesInOrbit – jamespick Jan 03 '14 at 22:02
  • @InsertNameHere: Now's the time to go and look it up. :) This should be covered pretty well in [your C++ book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – Lightness Races in Orbit Jan 03 '14 at 22:03
  • Thanks a lot this actually saved me loads of time. – jamespick Jan 03 '14 at 22:06
  • 1
    @InsertNameHere: Good :) – Lightness Races in Orbit Jan 03 '14 at 22:08
3

sizeof returns the types size in bytes, not the length of an array. So, to get method #1 to work, you'll have to store the length of the array.

Sebastian
  • 8,046
  • 2
  • 34
  • 58
2

You should use countof instead of sizeof:

template <typename T, size_t N> size_t countof( T (&array)[N] ){return N;}

I don't know exactly why it works (I mean I don't know how to write it if I loose it) but I use it (I will try to understand it - now!)

Another method I know better how to explain is using sizeof(arr)/sizeof(int).

Avoid using "special case" values when you can. There are always causing problems.

Wladimir Palant
  • 56,865
  • 12
  • 98
  • 126
2

There are already some very good answers written but I just wanted to add an ugly one:

If you want the size of the array in the way you write it

int *arr = (int*)malloc(16);

the size would depend on the size of an int on your system, it could be e.g 4 bytes per int so max 4 ints would fit in. In order to keep track of the size of what you have allocated you will need to manually enter the size in the allocated block e.g.

int n = 4;
int *arr = (int*)malloc((n+1)*sizeof(int)); 
*arr = 4;

then move the pointer

++arr;

whenever you need the size, check *(arr-1)

when you free the block make sure to use free(arr-1)

probably best to wrap them in some kind of function to hide the ugliness.

I really do not recommend this method since you are programming in C++, avoid malloc/free since they are not very C++ compatible, i.e. they know nothing about constructors, instead use new/new[]/delete/delete[] also vector<> is one of my favorite templates, once you know how to use that arrays will be a breeze.

AndersK
  • 35,813
  • 6
  • 60
  • 86