I think I lost my whole C++ knowledge...
What I want is to initialize a 2D unsigned char array in a proper (readable) way:
My approaches:
#define RADIO_ONOFF 0
#define RADIO_P1 1
#define RADIO_P2 2
...
#define NR_OF_CODES = 5
#define CODE_LENGTH = 10
#1:
unsigned char** codes = new unsigned char*[NR_OF_CODES];
codes[RADIO_ONOFF] = new unsigned char[CODE_LENGTH]{ 9,180,88,11,33,4,0,255,64,191 }; // does not work
...
#2:
unsigned char ICODES[NR_OF_CODES][CODE_LENGTH];
ICODES[RADIO_ONOFF] = { 9,180,88,11,33,4,0,255,64,191 }; // same as above
...
#3:
class Test {
private:
unsigned char data[CODE_LENGTH];
public:
Test(unsigned char a1, unsigned char a2, unsigned char a3, unsigned char a4, unsigned char a5, unsigned char a6, unsigned char a7, unsigned char a8, unsigned char a9, unsigned char a10);
unsigned char* getData(void);
};
Test::Test(unsigned char a1, unsigned char a2, unsigned char a3, unsigned char a4, unsigned char a5, unsigned char a6, unsigned char a7, unsigned char a8, unsigned char a9, unsigned char a10) {
this->data[0] = a1;
this->data[1] = a2;
this->data[2] = a3;
this->data[3] = a4;
this->data[4] = a5;
this->data[5] = a6;
this->data[6] = a7;
this->data[7] = a8;
this->data[8] = a9;
this->data[9] = a10;
}
unsigned char* Test::getData(void) {
return data;
}
void setup() {
test[RADIO_ONOFF] = new Test( 9,180,88,11,33,4,0,255,64,191 );
test[RADIO_P1] = new Test( 9,180,88,11,33,4,0,255,64,192 );
...
}
#4
const unsigned char RADIO_ONOFF[] = { 9,180,88,11,33,4,0,255,64,191 };
const unsigned char RADIO_P1[] = { 9,180,88,11,33,4,0,255,64,192 };
...
Error message I get for #1 and #2: (code should compile for Arduino and it needs a setup-function)
In function 'void setup()':
revTest:58: error: expected primary-expression before '{' token
revTest:58: error: expected `;' before '{' token
OK - my questions:
To me - #3 and #4 are nice and readable. Effort for #3 is the highest - but I think it´s the
fastest way if I want do uses the array in a switch statement. - True?
I thought array initialization in #1 and #2 should work this way????
Very Arduino specific:
I am not sure what has to be defined inside of setup() and what should go outside of setup(). static initialization and global outside, dynamic inside or what?
I have red about PROGMEM for Arduino - I think it´s not worth the effort in this case. I am right? (I think I`ll have about 50 different codes...)
thx!
Before answering your questions, let's look at what's going wrong with solutions 1 and 2.
The problem with solutions 1 and 2 is that you're using an initialiser ( i.e. the `{} syntax ), where your compiler is expecting an assignment expression.
Initialisation syntax can only be used at the point where the variable is declared. Roughly speaking, initialisation should be understood as giving a value to a variable as soon as it is constructed. Assignment should be understood as giving a value to a variable that has already been constructed somewhere else.
So when you do:
unsigned char** codes = new unsigned char*[NR_OF_CODES];
You are doing initialisation. You are initialising the variable codes to a freshly allocated array of pointers to unsigned char.
On the next line, you are then telling the compiler you are doing an assignment. You're using the = sign and assigning to codes, which was declared on the previous line - compiler sees this as assignment.
codes[RADIO_ONOFF] = new unsigned char[CODE_LENGTH] ...
But then, immediately afterwards, you attempt to use initialisation syntax.
Your compiler is complaining because it's read this:
codes[RADIO_ONOFF] = new unsigned char[CODE_LENGTH] ...
as a complete expression. It read that as you're allocating an array of CODE_LENGTH bytes and assigning it to the RADIO_ONOFF th member of codes.
And it expected you to stop there, with a semi colon but you continued and added the initalisation syntax {}. It doesn't understand, because you are mixing assignment and initialisation together - which are two separate things. That's why you're getting the "I expect a semi colon" type error from the compiler.
To answer your questions, both solution 3 and 4 are taking the long way round. There are quicker ways of initialising a 2D array in C++. I also agree with previous answer about using uint8_t.
Would something like this be more suitable?
uint8_t codes[CODE_LENGTH][NR_OF_CODES] =
{{0, 1, 2, 3, 4, 5, 6, 7},
{0, 1, 2, 3, 4, 5, 6, 7},
{0, 1, 2, 3, 4, 5, 6, 7},
{0, 1, 2, 3, 4, 5, 6, 7} };
A good way to read array syntax is to take the final (rightmost) value in the square brackets [] as the size of some array, and then work backwards.
So uint8_t codes[CODE_LENGTH][NR_OF_CODES] will decode out to an array of size NR_OF_CODES of something. And to get that something go left, and we see uint8_t codes[CODE_LENGTH] - so it's an array of length NR_OF_CODES of arrays of uint8_t, each of length CODE_LENGTH.
I hope that helps.
NB. In answer to your comment about needing to index the array with named indices - there's nothing stopping you from referring to the individual members of codes via an index.
What you can do is initialise the whole thing via {0} - shorthand for initialising all members to 0.
And you can assign members of the RADIO_ONOFF array (or any array for that matter) individually e.g.
codes[RADIO_ONOFF][3] = 255;
Try this example - and note the output:
#include <iostream>
const int NR_OF_CODES = 4;
const int RADIO_ONOFF = 0;
const int CODE_LENGTH = 11;
const unsigned char RADIO_ONOFF_ARR[] = { 180,99,33,11,22,33,55, 22,22,33, 10};
int main()
{
unsigned char codes[CODE_LENGTH][NR_OF_CODES] = {
{0},
};
std::cout << "Before:\n";
for(int x = 0; x < CODE_LENGTH; x++)
{
std::cout << static_cast<int>(codes[RADIO_ONOFF][x]) << ", ";
}
codes[RADIO_ONOFF][3] = 3;
std::cout << "\nAfter:\n";
for(int x = 0; x < CODE_LENGTH; x++)
{
std::cout << static_cast<int>(codes[RADIO_ONOFF][x]) << ", ";
}
// or try memcpy
memcpy(codes[RADIO_ONOFF], RADIO_ONOFF_ARR, sizeof RADIO_ONOFF_ARR);
std::cout << "\nAfter Memcpy:\n";
for(int x = 0; x < CODE_LENGTH; x++)
{
std::cout << static_cast<int>(codes[RADIO_ONOFF][x]) << ", ";
}
char c;
std::cin >> c;
return 0;
}
First off all, since this is tagged C++, I'm going to say that there is no need to do #define. You now have access to static const variables that do the same, but are type safe.
Here's what the Google C++ style guide has to say about braced lists:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Braced_Initializer_Lists
I generally follow this guide when I'm not working on a project with an already setup style. Also, I should mention that style is really subjective, so you may end up getting a wide range of answers.
Also, don't use char, where you just want to store byte data. That's what uint8_t is for.
Also, see this SO thread for all your options of how to initialize your arrays: How to initialize all members of an array to the same value? In most of your cases since they are just holding non-changing constants, you can get away with making them static const.
Like this:
static const size_t kMyCodeArraySize = 14; // an example
static const uint8_t[kMyCodeArraySize] = {1, 2, 3, 4}; // example intialization
Related
I want to dump chars from a Lora transmitter using Arduino Nano. With this line I assume it can be store the chars into an array:
char* dump = (char)LoRa.read();
char in[255];
strcpy(in, dump);
char str[] = in;
But unfortunately I get this compiler error:
exit status 1
initializer fails to determine size of 'str'
How I fix it?
UPDATE
I give my entire code. I used shox96 shox96 from siara-cc for my objective to compress the data from Lora.read().
void print_compressed(char *in, int len) {
int l;
byte bit;
//Serial.write("\nCompressed bits:");
for (l=0; l<len*8; l++) {
bit = (in[l/8]>>(7-l%8))&0x01;
//Serial.print((int)bit);
//if (l%8 == 7) Serial.print(" ");
}
}
void loop() {
char* dump = (char)LoRa.read();
char in[255];
strcpy(in, dump);
char str[] = in;
char cbuf[300];
char dbuf[300];
int len = sizeof(str);
if (len > 0) {
memset(cbuf, 0, sizeof(cbuf));
int ctot = shox96_0_2_compress(str, len, cbuf, NULL);
print_compressed(cbuf, ctot);
memset(dbuf, 0, sizeof(dbuf));
int dlen = shox96_0_2_decompress(cbuf, ctot, dbuf, NULL);
dbuf[dlen] = 0;
float perc = (dlen-ctot);
perc /= dlen;
perc *= 100;
Serial.print(ctot);
Serial.write(",");
Serial.println(dlen);
}
delay(1000);
}
The compiler can only supply the size of an array for you on creation if it has a brace enclosed initializer list. Like this:
int array[] = {1, 2, 3, 4, 5};
If you're doing anything other than that then you need to put a number inside those braces. Since you're making a copy of the array in and that array is 255 char then this one needs to be 255 char as well in order to accommodate.
char str[255] = in;
My comment on your question still stands though. This answer clears your compiler error, but I don't think it is really a solution to your larger problem. But without seeing more of your code and knowing more about it I can't tell much about it. You already have two copies of this data by the time you get to that line. I'm not sure why you think you need to have a third.
I have a char buffer that contains several integers one after the other without any breaks between them, where the offsets of each separate number are known in advance. For example "1234123123456", where from position [0] to [3] it would be the first number, [4] to [6] the second, and [7] to the end would be the third.
Is there any way to convert these different sections to ints without altering the buffer? Please no usage of std::string since it is inefficient for my purposes.
You can write a simple conversion function like this:
int convert_slice(const char *s, size_t a, size_t b) {
int val = 0;
while (a < b) {
val = val * 10 + s[a++] - '0';
}
return val;
}
int main(void) {
char buffer[] = "12345678901234567890";
printf("%d\n", convert_slice(buffer, 0, 4);
printf("%d\n", convert_slice(buffer, 4, 6);
printf("%d\n", convert_slice(buffer, 6, 11);
printf("%d\n", convert_slice(buffer, 11, 20);
return 0;
}
Will produce:
1234
56
78901
234567890
Note that I use 2 index arguments, the first is included and the second is excluded. This is more consistent with C and C++ practices. You could also use a more classic C++ API such as int convert_slice(const char *a, const char *b);
One clean way to do this without writing your own parsing code or making temporary copies is to use sscanf:
sscanf(src+start_offset, "%4d", &result);
If the length of the field (4 in the example) is not constant, though, you'll need either snprintf to construct a format string to pass to sscanf, or an array of possible format strings for the sizes you need.
I'm doing a little graphics programming and I have a two dimentional array (that varies in size during program execution) that I store using openGL.
So when I go to access it, all I get is a void pointer back.
To make the logic easier, I want the compiler to pretend that it is, and use it as, a 2D array (because arr[i][j] is more concise and less error prone than ptr[i * y + j]).
This clever method of casting I found works fine in GCC (on the linux machines at uni):
Vertex (&vertices)[tess][tess] = *reinterpret_cast<Vertex (*)[tess][tess]>(
glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY)
);
Which basically casts the block of memory pointer openGL gave me to a tess X tess 2D array, and creates a reference of that type to point at it.
This allows me to access the memory like vertices[i][j].
Vertex is just a typedefed struct containing floats
However, at home on my Windows machine, VS'12 has a hissy fit, complaining that it requires the integers where tess is written to be constant (specifically; error C2057: expected constant expression).
I have no idea why.
Now, I understand that VS doesn't support VLA's, but I am not creating an array here, I'm creating a reference to something that I don't know the size of 'till runtime.
So it shouldn't care if the size changes between function calls, right? Why is this not allowed?
Not to be deterred I tried using std::array
std::array<std::array<Vertex, tess>, tess>& vertices;
And apart from the obvious references must be initialized this test didn't help me because it still complained about expression must have a constant value (specifically; error C2975: '_Size' : invalid template argument for 'std::array', expected compile-time constant expression)
I am at a loss at what to try here, I was so proud of the reinterpret_cast and how simple it made things and was sure I wasn't using a method that was contravening the standard.
I don't want to create a std::vector from the pointer then copy the data from that dynamic array back into the pointer location when I'm finished; that just seems so inefficient when the memory block is already just sitting there!
There's no way to create a vector around a pre-existing block of memory, is there? ..no that sounds silly.
I want to see if this can be done without giving up and just using it as Vertex*; Ideas?
Can someone enlighten me as to why it isn't working in VS?
Is there something I can do to get it working (extensions/updates to VS)?
Does VS'13 add support for this?
I am also getting the error C2087: 'vertices' : missing subscript that I can't explain.
As well as these other errors that seem to show VS desperately wants tess to be constant:
error C2466: cannot allocate an array of constant size 0
error C2540: non-constant expression as array bound
error C2440: 'initializing' : cannot convert from 'Vertex [1][1]' to 'Vertex (&)[][1]'
Well that was fun; I implemented a class to handle exactly what I wanted.
It's not as typesafe as I'd like, but I learned a lot doing it
Much like how I felt implementing should-be-a-part-of-the-specification, syntactic-sugar-esque functionality for javascript before I discovered jQuery.
Basically, instead of being able to do this.
int (&array)[x][y] = *reinterpret_cast<int (*)[x][y]>(pointer);
You will have to do this
MDAI<int, 2> array = MDAI<int, 2>(pointer, x, y);
But other than that it works flawlessly! :D
I initially wrote just a specialised TwoDArray class but found I actually had some 3D arrays too.
So instead of implementing a 3D version (that returned TwoDArray when you drilled down) I made something more generic and can help with arrays of as many dimensions as you'd like.
#include <Windows.h>
#include <iostream>
/*MultiDimensional Array Interpretation
has the compiler use a flat pointer reference as if it were a faceted array
C++11/GCC VLA-supporting equivalent:
int (&array)[x][y] = *reinterpret_cast<int (*)[x][y]>(pointer);
using MDAI, <C++11 and MSVS compatible:
MDAI<int, 2> array = MDAI<int, 2>(pointer, x, y);
*/
template<class Type, unsigned int dimension>
class MDAI {
private:
Type* array;
//+1 to guard against zero-length-array
unsigned int bounds[dimension + 1];
public:
//unfortunately I can't use `unsigned int &(dimensions)[dimension]` to make it safe
//because of how operator[]() tries to construct its return value
/*constructor*/
MDAI(Type* array, unsigned int* bounds)
: array(array)
{
std::copy(bounds, bounds + dimension, this->bounds);
}
/*programmer usable constructor for typing of the dimensions, instead of having to declare an array*/
MDAI(Type* array, ...)
: array(array)
{
va_list arguments;
va_start(arguments, array);
for (int index = 0; index < dimension; ++index)
bounds[index] = va_arg(arguments, unsigned int);
va_end(arguments);
}
/*drills down one level into the multi dimensional array*/
MDAI<Type, dimension - 1> operator[](unsigned index) {
if (dimension < 1) {
std::cerr << "MDAI is not an array.\n";
throw 1;
}
if (index < 0 || index >= bounds[0]) {
std::cerr << "Index out of bounds.\n";
throw 1;
}
//figure out how many addresses to jump
for (unsigned int index2 = 1; index2 < dimension; ++index2)
index *= bounds[index2];
return MDAI<Type, dimension - 1>(array + index, bounds + 1);
}
/*'dereferences' the array to get a reference to the stored value*/
Type& operator*() {
if (dimension > 0) {
std::cerr << "MDAI is an array.\n";
throw 1;
}
return *array;
}
/*allows the compiler to automagically 'convert' the MDAI into whatever the user thinks it is*/
operator Type&() {
return **this;
}
/*makes assignment work automagically too!*/
MDAI<Type, dimension>& MDAI<Type, dimension>::operator=(Type value) {
**this = value;
return *this;
}
};
Testing a three-dimensional array of bounds 2-4-3:
void main(unsigned int argC, char** argV) {
using namespace std;
int array[2][4][3] = {
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
{10, 11, 12}
},
{
{13, 14, 15},
{16, 17, 18},
{19, 20, 21},
{22, 23, 24}
}
};
//cast array to pointer, then interpret
MDAI<int, 3> mdai((int*)array, 2, 4, 3);
//testing correct memory access
cout << 15 << ' ' << mdai[1][0][2] << endl;
//testing modifcations using mdai are in array
mdai[0][2][1] = -1;
cout << array[0][2][1] << ' ' << mdai[0][2][1] << endl;
//testing modifications in array show up in mdai
array[1][3][2] = -23;
cout << -23 << ' ' << mdai[1][3][2] << endl;
//testing automatic type casting
cout << -15.0 << ' ' << mdai[0][0][1] * -7.5 << endl;
}
It's as seamless as it would have been had I left it as an array reference.
For compile-time safety I wanted to have redeclare operator*() as, specifically;
Type& MDAI<Type, 0>::operator*()
so you could only call it on a <X, 0>
But I couldn't figure it out.
Similarly get operator[]() to only appear for dimensions greater than 0
Oh well, runtime checking will have to be good enough
My current project requires me to fill an array based upon some other values. I know there's the shortcut:
int arr[4][4] = { {0,0,0,0} , {0,0,0,0} , {0,0,0,0} , {0,0,0,0} };
But in this case, I need to fill the array after its declaration. I currently have my code formatted like this:
int arr[4][4];
if(someothervariable == 1){
arr = { {1,1,1,1},
{1,2,3,4},
{2,,3,4,5},
{3,4,5,6} };
}
But it won't compile. Is there a way to make use of the mentioned shortcut in my case? If not, whats the best fix available? I'd appreciate a way to set it without explicitly assigning each element? ie: arr[0][0] = ...
How about using std::copy() ?
int arr[4][4];
if(someothervariable == 1){
const static int a2[4][4] = { {1,1,1,1},
{1,2,3,4},
{2,3,4,5},
{3,4,5,6} };
std::copy(&a2[0][0], &a2[0][0]+16, &arr[0][0]);
}
No, array initialization syntax is for array initialization. Although, you can use memset if all the values are the same byte.
The boost.assign library adds some interesting syntax for modifying/filling collections, but AFAIK it doesn't support C style arrays (only C++ and Boost containers).
In the current version of C++ language the only way to do it is to copy it from some original
int arr[4][4];
if (someothervariable == 1)
{
const int SOURCE[4][4] = // make it `static` if you prefer
{
{1, 1, 1, 1},
{1, 2, 3, 4},
{2, 3, 4, 5},
{3, 4, 5, 6}
};
assert(sizeof arr == sizeof SOURCE); // static assert is more appropriate
memcpy(&arr, &SOURCE, sizeof arr);
}
The source "constant" can be declared as static in order to avoid re-initialization, if the compiler is not smart enough to optimize it by itself.
In the future version of the language a feature similar to C's compound literals is planned, which will provide support for immediate initialization (basically what you tried to do in your original post).
If you wish to fill the array with a single value:
#include<algorithm>
#include<vector>
// ...
std::vector<int> arr;
std::fill(arr.begin(), arr.end(), VALUE); // VALUE is an integer
If you wish to calculate the value for each element:
struct get_value {
int operator()() const { /* calculate and return value ... */ }
};
std::generate(arr.begin(), arr.end(), get_value());
If you are setting everything to the same value (such as zero), you may be able to get away with ...
memset (arr, 0, sizeof (arr));
Note that this is fraught with perils. You have to know your type sizes and all that jazz.
However, it appears that that will not suffice for you. If you want to fill the array with different values, I can only only think of two ways of doing this.
Method #1. (Can be a pain the butt)
arr[0][0] = 1;
...
arr[0][3] = 1;
arr[1][0] = 1;
...
arr[1][3] = 4;
arr[2][0] = 2;
...
arr[2][3] = 5;
arr[3][0] = 3;
...
arr[3][3] = 6;
Method #2.
Predefine a set of arrays and switch between them using a pointer;
int arr1[4][4] = {
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0} };
int arr2[4][4] = {
{1,1,1,1},
{1,2,3,4},
{2,,3,4,5},
{3,4,5,6} };
int *arr[4];
Now you only have the four (4) values of *arr[] to set instead of setting everything. Of course, this really only works if your arrays will be filled with predetermined constants.
Hope this helps.
I'm not sure if I like this solution or not, but C/C++ will give you assignment convenience if you wrap the array inside a struct with the minor cost of then having to use the struct name to get at the array:
typedef struct {
int data[4][4];
} info_t;
info_t arr;
if (someothervariable == 1){
static const info_t newdata = {{ // since this is static const, there generally
// won't be a copy - that data will be 'baked'
// into the binary image (or at worst a
// single copy will occur)
{1,1,1,1},
{1,2,3,4},
{2,3,4,5},
{3,4,5,6}
}};
arr = newdata; // easy to assign new data to the array
}
int somethingelse = arr.data[1][2]; // a tiny bit less convenient to get
// to the array data
int arr[4][4];
if (someothervariable == 1) {
int tmp[4][4] = { {1, 1, 1, 1}, {1, 2, 3, 4}, {2, 3, 4, 5}, {3, 4, 5, 6} };
arr = tmp;
}
OK, I am trying to get a sub array from an existing array and I'm just not sure how to do it. In my example I have a very large array, but I want to create an array from the last 5 elements of the array.
An example of what I am talking about would be:
int array1 = {1,2,3,...99,100};
int array2[5] = array1+95;
I know this isn't correct, but I am having some trouble getting it right. I want to get the elements 96 through 100 in array1 and put them into array2 but I don't want to copy the arrays. I just want array2 to start at the 96 element such that array1[96] and array2[0] would be pointing to the same location.
for this:
"such that array1[96] and array2[0] would be pointing to the same location."
you can do:
int *arr2 = arr1 + 96;
assert(arr2[0] == arr1[96] == 97);
A reference hack from a C programmer willing to subvert the type system to get what works:
int (&array2)[5] = (int (&)[5])(*(array1 + 5));
Now array2 will be an array for all intents and purposes, and will be a sub-array of array1, and will even be passable to that famous C++ array_size template function. Though the best way to handle this hackery is to hide it with more hackery!
#define make_sub_array(type, arr, off, len) (type (&)[len])(*(arr + off));
int (&array2)[5] = make_sub_array(int, array1, 5, 5);
Nice. Terrible by some standards, but the end result a) looks pretty neat, b) does exactly what you want, c) is functionally identical to an actual array, and d) will also have the added bonus (or mis-feature) of being an identical reference to the original, so the two change together.
UPDATE: If you prefer, a templated version (sort of):
template <typename T, size_t M>
T (&_make_sub_array(T (&orig)[M], size_t o))[]
{
return (T (&)[])(*(orig + o));
}
#define make_sub_array(type, array, n, o) (type (&)[n])_make_sub_array(array, o)
int (&array2)[5] = make_sub_array(int, array1, 5, 5);
We still have to pass the type. Since one of our arguments must be used as part the cast, we cannot cleanly (IMHO) avoid the macro. We could do this:
template <typename T, size_t M, size_t N>
T (&make_sub_array(T (&orig)[M], size_t o))[N]
{
return (T (&)[N])(*(orig + o));
}
int (&array2)[5] = make_sub_array<int, 15, 5>(array1, 5);
But the goal here is to make the calling code as clean as possible, and that call is a bit hairy. The pure-macro version probably has the least overhead and is probably the cleanest to implement in this case.
You can use boost::iterator_range to represent "slices" of arrays/containers:
#include <iostream>
#include <boost/range.hpp>
int main()
{
int array[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
// Create a "proxy" of array[5..7]
// The range implements the concept of a random sequence containter
boost::iterator_range<int*> subarray(&array[5], &array[7]+1);
// Output: 3 elements: 5 6 7
std::cout << subarray.size() << " elements: "
<< subarray[0] << " "
<< subarray[1] << " "
<< subarray[2] << "\n";
}
Note that the iterator range "knows" about the size of the sub-array. It will even do bounds checking for you. You cannot get that functionality from a simple pointer.
The usefulness of Boost.Range will become more apparent once you learn about STL containers and iterators.
If you're into linear algebra, Boost.uBlas supports ranges and slices for its matrices and vectors.
For a completely different approach you could do something like.
vector<int> v0(array1 + 95, array1 + 100);
or
vector<int> v1(array1, array1 + 100);
vector<int> v2(v1.begin() + 95, v1.end());
This would make a real copy of the elements of your vector.
In C++ you can use an int pointer as an int array, so getting the array2 to start at item 96 in array1 is easy, but there isn't any way to give array2 a size limit, so you can do this
int array2[] = &array1[96];
or this
int *array2 = &array1[96];
but NOT this
int array2[5] = &array1[96]; // this doesn't work.
On the other hand, C++ doesn't enforce array size limits anyway, so the only real loss is that you can't use sizeof to get the number of elements in array2.
note: &array1[96] is the same thing as array+96
edit: correction - int array[] = &array[96] isn't valid, you can only use [] as a synonym for * when declaring a function parameter list.
so this is allowed
extern int foo(int array2[]);
foo (&array1[96]);
int array1[] = {1,2,3,...99,100};
int *array2 = &array1[96];
int arr[] = { 1, 2, 3, 4, 5};
int arr1[2];
copy(arr + 3, arr + 5, arr1);
for(int i = 0; i < 2; i++)
cout << arr1[i] << endl;
The code is not safe if the boundaries are not handled properly.
You said you don't want to copy the array, but get a pointer to the last five elements. You almost had it:
int array1[] = {1,2,3,...99,100};
int* array2 = &array1[95];