Using pointer for crossing over all elements in INTEGER array

14,105

Solution 1

The reason that you can iterate across a C-style string using pointers is that of the 256 different character values, one has been specifically reserved to be interpreted as "this is the end of the string." Because of this, C-style strings can't store null characters anywhere in them.

When you're trying to use a similar trick for integer arrays, you're noticing the same problem. If you want to be able to stop at some point, you'll have to pick some integer and reserve it to mean "this is not an integer; it's really the end of the sequence of integers." So no, there is no general way to take an array of integers and demarcate the end by a special value unless you're willing to pick some value that can't normally appear in the string.

C++ opted for a different approach than C to delineate sequences. Instead of storing the elements with some sort of null terminator, C++-style ranges (like you'd find in a vector, string, or list) store two iterators, begin() and end(), that indicate the first element and first element past the end. You can iterate over these ranges by writing

for (iterator itr = begin; itr != end; ++itr)
    /* ... visit *itr here ... */

This approach is much more flexible than the C-string approach to defining ranges as it doesn't rely on specific properties of any values in the range. I would suggest opting to use something like this if you want to iterate over a range of integer values. It's more explicit about the bounds of the range and doesn't run into weird issues where certain values can't be stored in the range.

Solution 2

In general, no unless you pick a sentinel value that's not part of the valid range of the data. For example, the valid range might be positive numbers, so you can use a negative number like -1 as a sentinel value that indicates the end of the array. This how C-style strings work; the NULL terminator is used because it's outside of the valid range of integers that could represent a character.

However, it's usually better to somehow pair up the array pointer with another variable that indicates the size of the array, or another pointer that points one-past-the-end of the array.

In your specific case, you can do something like this:

// Note that you don't have to specify the length of the array.
int array[] = {1,12,41,45,58,68};
// Let the compiler count the number of elements for us.
int arraySize = sizeof(array)/sizeof(int);
// or int arraySize = sizeof(array)/sizeof(array[0]);

int main()
{
    int* i;
    for(i = array; i != array + arraySize; i++)
        printf("%d ",*i);
}

You can also do this:

int arrayBegin[] = {1,12,41,45,58,68};
int* arrayEnd = arrayBegin + sizeof(arrayBegin)/sizeof(arrayBegin[0]);

int main()
{
    int* i;
    for(i = arrayBegin; i != arrayEnd; i++)
        printf("%d ",*i);
}

But given only a pointer, no you can't know how long the array it points to is. In fact, you can't even tell if the pointer points to an array or a single object! (At least not portably.)

If you have functions that must accept an array, either have your function require:

  • the pointer and the size of the array pointed by the pointer,
  • or two pointers with one pointing to the first element of the array and one pointing one-past-the-end of the array.

Solution 3

I'd like to give some additional advice: Never use some kind of sentinel/termination value in arrays for determining their bounds. This makes your programs prone to error and is often the cause for security issues. You should always store the length of arrays to limit all operations to their bounds and test against that value.

In C++ you have the STL and its containers.

In C you'll effectively end up using structures like

typedef struct t_int_array 
{
    size_t length;
    int data[1]; /* note the 1 (one) */
} int_array;

and a set of manipulation functions like this

int_array * new_int_array(size_t length)
{
    int_array * array;
    /* we're allocating the size of basic t_int_array 
      (which already contains space for one int)
      and additional space for length-1 ints */
    array = malloc( sizeof(t_int_array) + sizeof(int) * (length - 1) );
    if(!array)
        return 0;
    array->length = length;
    return array;
}

int_array * concat_int_arrays(int_array const * const A, int_array const * const B);
int_array * int_array_push_back(int_array const * const A, int const value);
/* and so on */

This method will make the compiler align the t_int_array struct in a way, that it's optimal for the targeted architecture (also with malloc allocation), and just allocating more space in quantities of element sizes of the data array element will keep it that way.

Share:
14,105
Miro
Author by

Miro

Hi there! 👋 I'm working on Torque and I'm excited about the future it can bring. To learn more visit https://www.torquetech.dev and if you think Torque can make a difference please join our community https://community.torquetech.dev 🚀

Updated on June 05, 2022

Comments

  • Miro
    Miro almost 2 years

    Is there a way to cross over all elements in integer array using pointer ( similiar to using pointer to cross over string elements).I know that integer array is not NULL terminated so when I try to cross over array using pointer it overflows.So I added NULL as a last element of an array and it worked just fine.

    int array[7]={1,12,41,45,58,68,NULL};
    int *i;
    for(i=array;*i;i++)
        printf("%d ",*i);
    

    But what if one of the elements in array is 0 ,that will behave just as NULL.Is there any other way that will implement pointer in crossing over all elements in integer array?