18

I have a dynamically allocated array of float and I need to pass this array as an argument to three different functions but each function need to get a different range of the array. Is there some way I can send the array with elements 0 to 23 to one function, elements 24 to 38 to another, and elements 39 to 64 to a third function.

In some languages(like python I think) you can do something like this:

somefunction(my_array[0:23]);
somefunction(my_array[24:38]);
somefunction(my_array[39:64]);

However I am using c++ and I am not aware of any way to do this in c++.

Does anybody know how to do this?

somefunction(); is a function from an API so I can not modify the arguments it takes.

4
  • How does somefunction know how large the array is? Commented Dec 2, 2011 at 22:13
  • somefunction(); is glTexCoordPointer(); from OpenGL Commented Dec 2, 2011 at 23:32
  • if you are using glTexCoordPointer() just pass my_array + n. Commented Dec 2, 2011 at 23:50
  • @PgrAm: Just edited my answer after seeing you now mention glTexCoordPointer(). If you have any other code for drawing something after setting the texture you should add it to your question. Commented Dec 3, 2011 at 0:32

7 Answers 7

15

If you write the functions to operate on a pair of forward iterators rather than an array, you could just pass it like so:

somefunction1(my_array, my_array + 24);
somefunciton2(my_array + 24, my_array + 39);
somefunction3(my_array + 39, my_array + 65);

Pointers are forward iterators, and this would allow the functions to be used over parts of vectors, queues, or other STL containers as well.

Sign up to request clarification or add additional context in comments.

4 Comments

If the 2nd arg represents the conventional end() iterator, aren't you off by one?
@Rob: these kind of functions interpret the second argument as 'one past the last element'. That's how the STL deals with iterators.
@xtofl: Yeah that's what he means - offsets of 24, 39, 65 as opposed to 23, 38, 64.
I can't do it this way because I can not modify somefunction();
9

The python example is making copies. If that's okay for your use case, you could do something like this (I'm swapping out your vanilla arrays for std::vector):

#include <iostream>
#include <vector>

void somefunction(std::vector<int> v) {
    std::cout << "vector has " << v.size() << " elements,"
        << " first value is " << *v.begin() << ","
        << " last value is " << *(v.end()-1) << std::endl;
}

int main() {
    std::vector<int> a;
    for (int i=0; i<65; i++) {
        a.push_back(i);
    }
    somefunction(std::vector<int>(a.begin(),a.begin()+23));
    somefunction(std::vector<int>(a.begin()+24,a.begin()+38));
    somefunction(std::vector<int>(a.begin()+39,a.begin()+65));
}

which outputs:

vector has 23 elements, first value is 0, last value is 22
vector has 15 elements, first value is 23, last value is 37
vector has 27 elements, first value is 38, last value is 64

But it sounds like you can't use std::vector, because somefunction() has a signature you can't change. Luckily, you can do similar gymnastics just manually copying parts of the array, as below:

#include <iostream>
#include <string.h>

void somefunction(int v[], int len) {
    std::cout << "vector has " << len << " elements,"
        << " first value is " << v[0] << ","
        << " last value is " << v[len-1] << std::endl;
}

int main() {
    int a[65];
    for (int i=0; i<65; i++) {
        a[i] = i;
    }
    int b[23];
    memcpy(b, a, 23*sizeof(int));
    somefunction(b, 23);
    int c[15];
    memcpy(c, a+23, 15*sizeof(int));
    somefunction(c, 15);
    int d[27];
    memcpy(d, a+38, 27*sizeof(int));
    somefunction(d, 27);
}

which again outputs:

vector has 23 elements, first value is 0, last value is 22
vector has 15 elements, first value is 23, last value is 37
vector has 27 elements, first value is 38, last value is 64

1 Comment

I don't think the Python example is making a copy but rather returns a view. Can you provide a reference?
7

Your function is going to need some way to determine the size of the array anyway. I suggest you make the function take begin and end iterators, in the style of the standard library algorithms, like so:

template<typename I>
void somefunction(I begin, I end);

Then, you can call it with your array like this:

somefunction(my_array, my_array + 24);
somefunction(my_array + 24, my_array + 39);
somefunction(my_array + 39, my_array + 65);

3 Comments

I can't do it this way because I can not modify somefunction();
@PgrAm: Then answer GMan's comment below your question, because when you pass an array to a function, it decays to a pointer and the size is lost.
somefunction(); is glTexCoordPointer(); from OpenGL
5

There are two ways you could do it:

void useArray(int array[], size_t len) { ... }
...
useArray(myArray, 24);
useArray(&myArray[24], 15);
useArray(&myArray[39], 26);

OR

void useArray(int *start, int *end) { ... }
...
useArray(myArray, myArray + 24);
useArray(myArray + 24, myArray + 39);
useArray(myArray + 39, myArray + 65);

The first is more of a C way, the second a more C++ way. Note that with the second way, the range is [start, end) - end isn't included in the range as you see a lot in C++.


EDIT: You edited your post to mention that you're using glTexCoordPointer(). In that case pass the start of the array to glTexCoordPointer(), which will be either myArray, myArray + 24 or myArray + 39.

The size of the array still has to be known though, and is passed to functions such as glDrawArrays or glDrawElements(), which will then start reading from the array. If you were using glDrawArrays(), the length of the array is passed as the second argument. Therefore your code could be something like:

glTexCoordPointer(..., ..., ..., my_array);
...
glDrawArrays(..., 0, 24);

glTexCoordPointer(..., ..., ..., my_array + 24);
...
glDrawArrays(..., 0, 15);

glTexCoordPointer(..., ..., ..., my_array + 39);
...
glDrawArrays(..., 0, 26);

4 Comments

+1 for emphasizing that there is a 'more C++ way'. Personally, I like to make the first case consistent with the following ones: use( myarray + 0, myarray + 23 )
I can't do it this way because I can not modify somefunction();
@AusCBloke glTexCoordPointer(..., ..., ..., my_array + 24); appears to do nothing but rotate the texture
@PgrAm: I'm not too sure about OpenGL stuff, but passing my_array + 24 will make it seem as if that's the start of the array.
0

There is no upper bound range checking, so you have to take care of that yourself. But you can pass &my_array[0] to one function, and &my_array[24] to another. Maybe add a len parameter to your function to take care of upper range.

Comments

0

You could refactor your functions to use 'iterators': a pointer to the begin and to the end of the array-range you're interested in:

 void somefunction( int* begin, int* end ) {
    for( int* i=begin; i != end; ++i ) {
       //stuff with *i
    }
 }


 // usage:
 somefunction( my_array+0, my_array+23 );
 somefunction( my_array+24, my_array+38 );
 somefunction( my_array+39, my_array+64 );

Bonus points: if you make your function a template, you can use it with other iterators too:

 template<typename T>
 void somefunction( T begin, T end ) {
    for( T i=begin; i != end; ++i ) {
       //stuff with *i
    }
 }

 vector<int> values(100);
 somefunction( values.begin(), values.end() );
 somefunction( values.rbegin(), values.rend() );

...

1 Comment

I can't do it this way because I can not modify somefunction();
0

I would return or do something like std::pair<pointer_type, pointer_type> which contains {Begin_Pointer, End_Pointer} so, Let's if we need to slice a raw array(in C/C++ land just a pointer) with specific parts/blocks. I would return take something like

pointer_type element_begin = raw_array+begin;
pointer_type element_end = raw_array+end;
std::pair<pointer_type, pointer_type> = std::make_pair(element_begin, element_end);

I will have a convenient function to which I give those begin and end non-negative values and it will return me a std::pair

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.