Define a pointer with an arbitrary span - c++

If I have a large array where the data streams are interleaved in some complex fashion, can I define a pointer p such that p + 1 is some arbitrary offset b bytes.
For example lets say I have 1,000,000 ints, 4 bytes each.
int* p_int = my_int_array;
This gives me *(p_int+1) == my_int_array[1] (moves 4 bytes)
I am looking for something like
something_here(b)* big_span_p_int = my_int_array;
which would make *(big_span_p_int + 1) == my_int_array[b] (moves 4*b or b bytes, whichever is possible or easier)
Is this possible? easy?
Thanks for the help.
EDIT:
b is compile time variable.

Using some of your code. There is no need to declare an additional pointer/array. Applying pointer arithmetic on p_int is enough to traverse and reach the number value you are seeking.
Let's look at this example:
int main() {
int my_int_array[5] {1,2,3,4,5};
int* p_int = my_int_array;
int b = 2;
std::cout << *(p_int + b) << std::endl; // Output is 3, because *p_int == my_int_array[0], so my_int_array[2] will give you the third index of the array.
}
Graphically represented:
Memory Address | Stored Value (values or memory addresses)
----------------------------------------------
0 | .....
1 | .....
2 | .....
3 | .....
4 | .....
5 | .....
6 | .....
7 | .....
8 | .....
. | .....
. | .....
. | .....
n-1 | .....
Imagine the memory as being a very big array in which you can access positions by its memory address (in this case we've simplified the addresses to natural numbers. In reality they're hexadecimal values). "n" is the total amount (or size) of the memory. Since Memory counts and starts in 0, size is equivalent to n-1.
Using the example above:
1. When you invoke:
int my_int_array[5] {1,2,3,4,5};
The Operating System and the C++ compiler allocates the integer array memory statically for you, but we can think that our memory has been changed. E.g. Memory address 2 (decided by the compiler) now has our first value of my_int_array.
Memory Address | Name - Stored Value (values or memory addresses)
-----------------------------------------------------
0 | .....
1 | .....
2 | my_int_array[0] = 1
3 | my_int_array[1] = 2
4 | my_int_array[2] = 3
5 | my_int_array[3] = 4
6 | my_int_array[4] = 5
7 | .....
8 | .....
. | .....
. | .....
. | .....
n-1 | .....
2. Now if we say:
int* p_int = my_int_array;
The memory changes again. E.g. Memory address 8 (decided by the compiler) now has a int pointer called *p_int.
Memory Address | Name - Stored Value (values or memory addresses)
-----------------------------------------------------
0 | .....
1 | .....
2 | my_int_array[0] = 1
3 | my_int_array[1] = 2
4 | my_int_array[2] = 3
5 | my_int_array[3] = 4
6 | my_int_array[4] = 5
7 | .....
8 | p_int = 2 (which means it points to memory address 2, which has the value of my_int_array[0] = 1)
. | .....
. | .....
. | .....
n-1 | .....
3. If in your program you now say:
p_int += 2; // You increase the value by 2 (or 8 bytes), it now points elsewhere, 2 index values ahead in the array.
Memory Address | Name - Stored Value (values or memory addresses)
-----------------------------------------------------
0 | .....
1 | .....
2 | my_int_array[0] = 1
3 | my_int_array[1] = 2
4 | my_int_array[2] = 3
5 | my_int_array[3] = 4
6 | my_int_array[4] = 5
7 | .....
8 | p_int = 4 (which means it points to memory address 4, which has the value of my_int_array[2] = 3)
. | .....
. | .....
. | .....
n-1 | .....
When doing memory allocation and pointer arithmetic in a simple case like this, you don't have to worry about the size in bytes of an int (4 bytes). The pointers here are already bound to a type (in this case int) when you declared them, so just by increasing their value by integer values, p_int + 1, this will make point p_int point to the next 4 bytes or int value. Just by adding the values to the pointers you will get the next integer.

If b is a constant expression (a compile-time constant), then pointer declared as
int (*big_span_p_int)[b]
will move by b * sizeof(int) bytes every time you increment it.
In C you can use a run-time value in place of b, but since your question is tagged [C++], this is not applicable.

Related

Weird results when printing not existing list elements in C++

So I am learning C++ at the moment and got some really weird results when I tried printing out element of a list of integers, that are actually out of range. (Don't ask why, I stumbled on that by accident)
This is my Code:
#include <iostream>
using namespace std;
int main() {
int nums[0] = {};
for (int i = 0; i <= 10; i++) {
cout << nums[i] << endl;
}
return 0;
}
Results of when I ran the code the first time:
0
17110752
0
4199367
0
0
0
65
0
4225392
0
Results of when I ran the code a second time:
0
1906400
0
4199367
0
0
0
65
0
4225392
0
Results of when I ran the code a third time:
0
15603424
0
4199367
0
0
0
65
0
4225392
0
Every time I run this programm, the second number seems to be diffrent.
I know why I get unexpected results, but I'm curious where these values come from.
Edit: "I know why I get unexpected results" is just poorly worded. What I meant was "I know that I get unexpected result, because I am calling a element that is not part of the list".
Are they values from the RAM?
Why are some value repeating and some not?
The result of compiling your code to (my invented) machine code is something like this.
1 main:
2 reserve basePtr, 2 ; reserve 2 slots on the stack, and store in basePtr
3 mov nums, basePtr ; num points at the first local variable
4 mov [nums], 0 ; int num[1] = {0} - set num to zero
5 mov i, basePtr + 1 ; i points at second slot for local variables
6 mov [i], 0 ; int i = 0;
7 for_loop:
8 cmp [i], 10 ;
9 jmp_above_or_equal fini ; exit loop
10 mov tmp, [nums+i] ;
11 call cout, tmp
12 call cout, std::endl ;
13 inc [i]
14 jmp for_loop
15 fini:
16 return 0
So we reserve 2 slots for variables, and then read beyond the reserved space.
Imagine the call works like this :-
Initial stack
+-----------+
| ret_main | // crt code which calls main
+-----------+
| nums[0] |
+-----------+
| i |
SP-> +-----------+
push param (e.g. tmp) creates a stack like so...
+-----------+
| ret_main | // crt code which calls main
+-----------+
| nums[0] |
+-----------+
| i |
+-----------+
| tmp |
SP-> +-----------+
With the call itself....
+-----------+
| ret_main | // crt code which calls main
+-----------+
| nums[0] |
+-----------+
| i |
+-----------+
| tmp |
+-----------+
| line_12 |
SP-> +-----------+
With this stack growing down through calls, your further requests are showing the memory values of the return address into your code, and the local variables of the previous call to cout.
If the stack grows the other way (more normal), a stack may look as so...
SP-> +-----------+
| line_12 |
+-----------+
| tmp |
+-----------+
| i |
+-----------+
| nums[0] |
+-----------+
| ret_main | // crt code which calls main
+-----------+
This is the normal direction for stacks in modern processors. In this case when you look further into the nums array, you are reading values of the return address for the function, and then the local variables which are from the function calling main.
In practice i is probably optimized into a register, and entry into a function would save some registry values based on the platform's calling conventions.
So the values you are reading, is likely to be in this order...
Registers saved by main
Values to detect against buffer overrun (which is happening here)
Return address to main
arguments to main
local variables in the function which calls main.
Why are they repeating. If the function calling main has copies of argv, then it would be likely the push to store argv are matched by the callers copy in local variables.
Why do some change. Since Address Space Layout Randomization (ASLR), processes normally launch with a random base address, and random stack location, making it harder to exploit a buffer overflow.

Double pointer arithmetic

I have a 2D matrix
matrix[m][n];
I know that matrix is a double pointer with type int**. I would like to obtain a double pointer pointing to a submatrix of the original matrix. For example, I want the submatrix to start for cell (1,1). How do I get such a double pointer from the original matrix[m][n]?
I know that matrix is a double pointer with type int**.
No, you don't. Arrays are not pointers. If you declared it as int matrix[m][n];, then the type of the expression matrix is int [m][n]; unless matrix is the operand of the sizeof or unary & operators, it will have its type converted ("decay") to int (*)[n] (pointer to n-element array of int).
The problem is that you can't create arbitrary submatrices by just declaring a pointer of the right type; C and C++ don't provide an easy way to "slice" arrays this way. You can certainly create a pointer of type int (*)[n-1] and assign the value of &matrix[1][1] to it (with an appropriate cast), but it won't do what you want.
EDIT
Now that I have a real keyboard in front of me I can expand on this a little bit.
Let's imagine a 3x3 matrix declared as follows:
int m[3][3] = {{0,1,2},{3,4,5},{6,7,8}};
We normally visualize such a matrix as
+---+---+---+
| 0 | 1 | 2 |
+---+---+---+
| 3 | 4 | 5 |
+---+---+---+
| 6 | 7 | 8 |
+---+---+---+
In C and C++, 2-dimensional arrays are laid out in row-major order1, 2, so the above matrix would be represented in memory as
+---+
m: | 0 | m[0][0]
+---+
| 1 | m[0][1]
+---+
| 2 | m[0][2]
+---+
| 3 | m[1][0]
+---+
| 4 | m[1][1]
+---+
| 5 | m[1][2]
+---+
| 6 | m[2][0]
+---+
| 7 | m[2][1]
+---+
| 8 | m[2][2]
+---+
So suppose you want the 2x2 submatrix starting at m[1][1]:
+---+---+---+
| 0 | 1 | 2 |
+---+---+---+
| 3 | +---+---+
+---+ | 4 | 5 |
| 6 | +---+---+
+---+ | 7 | 8 |
+---+---+
That corresponds to the following array elements:
+---+
m: | 0 | m[0][0]
+---+
| 1 | m[0][1]
+---+
| 2 | m[0][2]
+---+
| 3 | m[1][0]
+---+
+---+
| 4 | m[1][1]
+---+
| 5 | m[1][2]
+---+
+---+
| 6 | m[2][0]
+---+
+---+
| 7 | m[2][1]
+---+
| 8 | m[2][2]
+---+
That's not a contiguous subarray within m, so just declaring a pointer and setting it to &m[1][1] won't do what you really want. You'll need to create a separate matrix object and copy the elements you want to it:
int subm[2][2] = {{m[1][1], m[1][2]}, {m[2][1], m[2][2]}};
You can write a function to grab a 2x2 "slice" of your matrix like so:
void slice2x2( int (*mat)[3], int (*submat)[2], size_t startx, size_t starty )
{
for ( size_t i = 0; i < 2; i++ )
for ( size_t j = 0; j < 2; j++ )
submat[i][j] = mat[startx + i][starty + j];
}
int main( void )
{
int matrix[3][3] = {{0,1,2},{3,4,5},{6,7,8}};
int submat[2][2];
slice2x2( matrix, submat, 1, 1 );
// do something with submat
}
Pre-publication draft of the C 2011 standard, §6.2.5.1, ¶3.
Pre-publication draft of the C++ 2014 standard, §8.3.4, ¶9
A matrix defined as 2D array of constant size:
int matrix [m][n];
is stored as m contiguous blocks of n elements. You can therefore imagine this technically as a flat sequence of m*n elements in memory. You can use pointer arithmetic to find the start of a row, or to find a specific element. But you can't locate a submatrix int that way.
The "double" pointer:
int **pmatrix;
obeys a different logic: it is a pointer to a pointer and works as an array of m pointers pointing at lines of n consecutive elements. So your elements are not necessarily consecutive. You can use pointer arithmetic and indirection to locate the start of a row or a specific item. But again this can't address a submatrix.
Both matrix and pmatrix can be used with 1D or 2D indexing, but the compiler generates different code to address the elements.
For getting sub-matrices you have to make iterations to find the right elements, using vertical and horizontal offsets, but you can't imagine to pass somehow a pointer to the sub-matrix if you don't copy the right elements in a new matrix of target's size.

C++ Copy Array Without dependency on original [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
How would I copy an array to a new array if i want the new array to not be dependent on the original array in C++. I know it has to do with using pointers but i am new to C++ and don't quite understand how this works
Short Answer
If you have 2 arrays defined as 10-byte each, say unsigned char arrayOne[10], arrayTwo[10];, they are already independent, and copying one into the other could be easily done this way:
for(unsigned i=0; i < 10; i++)
arrayTwo[i] = arrayOne[i];
you could also use memcpy:
memcpy(arrayTwo, arrayOne, 10); // 10 bytes copied from arrayOne to arrayTwo
and you could also use std::copy:
std::copy(arrayOne, arrayOne+10, arrayTwo); // Copy 10 elements from arrayOne to ArrayTwo
Long Answer
If you perform a copy of an array, the new array won't have any dependency on the original after the copy, if I am correctly understanding what you mean with "dependency".
It is more clear if you think of it from the memory point of view, and not from language point of view. An array is a sequence of values stored together in memory. Lets consider this code:
unsigned char myArray[10] { 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 };
After compilation and execution, these 10 bytes are stored together at a given location in memory. Imagine that location to be 0x1234 (For simplicity, consider our computer to have a 16-bits memory):
Location |0x1234|0x1235|0x1236| ....
---------------------------------------------------
Content | 12 | 14 | 16 | .....
---------------------------------------------------
In this context, you have 10 bytes stored, and a 2-byte variable called myArray which is also taking 2 bytes in memory, like this:
myArray myArray values
--------------- ----------------------
Location |0x0333|0x0334| .... |0x1234|0x1235|0x1236| .....
---------------------------------------------------
Content | 0x12 | 0x34 | .... | 12 | 14 | 16 | .....
---------------------------------------------------
Then, when you do something like this:
myArray[2] = 99;
You are effectively doing this:
*(myArray + 2) = 99;
which, in turn, means this:
*(0x1234 + 2) = 99;
This is the way pointers work. myArray is a pointer: a variable that holds the address where your array starts. Knowing that the array has all the elements consecutive, and each element occupies 1 byte, accessing the element 8 is accessing the start of the array plus 8, that is *(myArray + 8) or myArray[8].
So, if you wanted to make an independent copy of the array, you need another 10 bytes located in a different place in memory, and another pointer to the start of these new 10 bytes: that is, another array. This code does it:
unsigned char myArray[10] { 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 };
unsigned char otherArray[10];
for(unsigned i=0; i < 10; i++)
otherArray[i] = myArray[i];
This creates two independent arrays with the same content: two spaces of 10 bytes, with their two pointers to their locations in memory. Let's do an opperation to the second array:
otherArray[2] = 99;
imagining that otherArray = 0x4455, this would be the same as:
*(0x4455 + 2) = 99;
Let's imagine the result of this in our imaginary 16-bits memory:
myArray myArray values
--------------- ----------------------
Location |0x0333|0x0334| .... |0x1234|0x1235|0x1236| .....
---------------------------------------------------
Content | 0x12 | 0x34 | .... | 12 | 14 | 16 | .....
---------------------------------------------------
^^^^^^
Original left untouched
otherArray otherArray values
--------------- ----------------------
Location |0x0422|0x0423| .... |0x4455|0x4456|0x4457| .....
---------------------------------------------------
Content | 0x44 | 0x55 | .... | 12 | 14 | 99 | .....
---------------------------------------------------
^^^^^
Changed value
Then, we have our 2 arrays, one of them being copy of the other, but completely independent.

Odd bit operator in the increment statement of a for loop [duplicate]

This question already has answers here:
meaning of (number) & (-number)
(4 answers)
Closed 8 years ago.
Given this for loop:
for(++i; i < MAX_N; i += i & -i)
what is it supposed to mean? What does the statement i += i & -i accomplish?
This loop is often observed in binary indexed tree (or BIT) implementation which is useful to update range or point and query range or point in logarithmic time. This loop helps to choose the appropriate bucket based on the set bit in the index. For more details, please consider to read about BIT from some other source. In below post I will show how does this loop help to find the appropriate buckets based on the least significant set bits.
2s complementary signed system (when i is signed)
i & -i is a bit hack to quickly find the number that should be added to given number to make its trailing bit 0(that's why performance of BIT is logarithmic). When you negate a number in 2s complementary system, you will get a number with bits in inverse pattern added 1 to it. When you add 1, all the less significant bits would start inverting as long as they are 1 (were 0 in original number). First 0 bit encountered (1 in original i) would become 1.
When you and both i and -i, only that bit (least significant 1 bit) would remain set and all lesser significant (right) bits would be zero and more significant bits would be inverse of original number.
Anding would generate a power of 2 number that when added to number i would clear the least significant set bit. (as per the requirement of BIT)
For example:
i = 28
+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |
+---+---+---+---+---+---+---+---+
*
-i
+---+---+---+---+---+---+---+---+
| 1 | 1 | 1 | 0 | 0 | 1 | 0 | 0 |
+---+---+---+---+---+---+---+---+
I I I I I S Z Z
Z = Zero
I = Inverted
S = Same
* = least significant set bit
i & -i
+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
+---+---+---+---+---+---+---+---+
Adding
+---+---+---+---+---+---+---+---+
| 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+
x
x = cleared now
Unsigned (when i is unsigned)
It will work even for 1s complementary system or any other representation system as long as i is unsigned for the following reason:
-i will take value of 2sizeof(unsigned int) * CHAR_BITS - i. So all the bits right to the least significant set bit would remain zero, least significant bit would also remain zero, but all the bits after that would be inverted because of the carry bits.
For example:
i = 28
+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |
+---+---+---+---+---+---+---+---+
*
-i
0 1 1 1 1 1 <--- Carry bits
+---+---+---+---+---+---+---+---+
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+
+---+---+---+---+---+---+---+---+
- | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |
+---+---+---+---+---+---+---+---+
----------------------------------------
+---+---+---+---+---+---+---+---+
| 1 | 1 | 1 | 0 | 0 | 1 | 0 | 0 |
+---+---+---+---+---+---+---+---+
I I I I I S Z Z
Z = Zero
I = Inverted
S = Same
* = least significant set bit
i & -i
+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
+---+---+---+---+---+---+---+---+
Adding
+---+---+---+---+---+---+---+---+
| 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+
x
x = cleared now
Implementation without bithack
You can also use i += (int)(1U << __builtin_ctz((unsigned)i)) on gcc.
Live example here
A non obfuscated version for the same would be:
/* Finds smallest power of 2 that can reset the least significant set bit on adding */
int convert(int i) /* I purposely kept i signed as this works for both */
{
int t = 1, d;
for(; /* ever */ ;) {
d = t + i; /* Try this value of t */
if(d & t) t *= 2; /* bit at mask t was 0, try next */
else break; /* Found */
}
return t;
}
EDITAdding from this answer:
Assuming 2's complement (or that i is unsigned), -i is equal to ~i+1.
i & (~i + 1) is a trick to extract the lowest set bit of i.
It works because what +1 actually does is to set the lowest clear bit,
and clear all bits lower than that. So the only bit that is set in
both i and ~i+1 is the lowest set bit from i (that is, the lowest
clear bit in ~i). The bits lower than that are clear in ~i+1, and the
bits higher than that are non-equal between i and ~i.

Int into Array C++ help please

I am trying to separate an integer into an array. I have been using modulo 10 and then dividing by 10 but I believe that will only work for numbers 6 digits or less I may be wrong but it is not working for me. This is what I have:
for(int i=0; i<=8; i++){
intAr[i] = intVal%10;
intVal /= 10;
}
It is not working for me and help would be lovely
The problem i guess you have is that the number in the array is reversed. So try this:
for(i=8;i>=0;i--)
{
intAr[i] = intVal%10;
intVal /= 10;
}
This will work and have the number stored correctly in the array
If you are expecting the numbers to be stored in your array right-to-left, you'll need to reverse the way your store the values:
for(int i=0; i < 9; i++)
{
intAr[9 - i - 1] = intVal % 10;
intVal /= 10;
}
This will store your number (103000648) like this
|-0-|-1-|-2-|-3-|-4-|-5-|-6-|-7-|-8-|
| 1 | 0 | 3 | 0 | 0 | 0 | 6 | 4 | 8 |
instead of
|-0-|-1-|-2-|-3-|-4-|-5-|-6-|-7-|-8-|
| 8 | 4 | 6 | 0 | 0 | 0 | 3 | 0 | 1 |