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.
Related
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.
This question already has answers here:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Closed 5 years ago.
Known that sizeof(std::string) is 8, sizeof(int) is 4.
class Test1
{
int i; // 4
std::string str; // 8
};
sizeof(Test1) is 16, because 8 = N1 * 4 and 16 = N2 * 8. (N1 and N2 are natural numbers)
However, if I replace std::string with char [8] as below:
class Test2
{
int i; // 4
char ch[8]; // 8
};
I don't know why sizeof(Test2) gives me 12.
4 + 8 = 12, so 12 bytes is the minimum amount of memory to fit a 4 and a 8 byte object.
However, there is another consideration besides the total number of bytes of the subobjects. Each subobject has a particular alignment requirement.
The alignment of std::string depends on its complete subobjects, which are implementation defined. It appears, that std::string on your implementation has to be aligned to an 8 byte boundary. As a consequence, the alignment requirement of Test1 is also 8, and there must be 4 bytes of padding after the member i. So, the size of Test1 is the sum of the sizes of the subobjects + the pad bytes, which totals 4 + 8 + 4 = 16.
char and consequently char[8] have alignment requirement of 1. Therefore the alignment requirement of Test2 is 4 (because of int member) and no padding is required after the member i. Since there is no padding, the size of Test2 matches the sum of the sizes of the subobjects.
Another point of view is that the size must be a multiple of the alignment requirement. 16 is the smallest multiple of 8 (alignment of Test1) that is greater than or equal to 12. 12 is the smallest multiple of 4 (alignment of Test2) that is greater than or equal to 12.
The alignment of char is 1, and this holds for arrays of characters too. So no padding is added between the class members. Thus you get the size as 4 + 8 = 12.
This question already has answers here:
Multi-dimensional array initialization
(3 answers)
Closed 7 years ago.
I've seen that these types of array are sometimes seen as a matrix. I had a teacher who said that this was an easy way to look at it, and that the real way it looks is in a linear form. For example:
int a[2][3][2] = {0, 1, 2, 3 , 4, 5, 6, 7 , 8, 9, 10, 11};
How would you represent this in a linear way?
As far as memory layout is concerned,
int a[2][3][2] = { { { 0, 1 }, { 2, 3 }, { 4, 5 } },
{ { 6, 7 }, { 8, 9 }, { 10, 11 } } };
is the same as:
int b[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
and a[i][j][k] is equivalent to b[i * 6 + j * 2 + k].
For your three-dimensional example, you can use an array b of size 2*3*2 = 12 and access the former element a[i][j][k] via b[k + 2 * ( j + 3* i)].
Alternatively, any other rearrangement will do as well, for example b[i + 2 * ( j + 3* k)]. The optimal choice depends on how you mainly want to traverse the array.
In general, one can translate any array
a[0 ... N_1-1][0 ... N_2-1] ... [0 ... N_k-1]
into a linear array b of size N_1 * N_2 * ... * N_k. In practice, the only thing you have to change is the index function: so when you want to access element a[i_1][i_2] ... [i_k] in your original array, you use the following instead
b[i_k + N_k * ( i_{k-1} + N_{k-1} * ( ... N_2 * i_1) ...))]
An array is a number of elements, stored consecutively in memory.
A 2D array is an array of arrays.
As such, a 2D array is a number of arrays, stored consecutively in memory. It follows that all the elements of the 2D array are stored consecutively in memory.
In your concrete example, the compiler will allocate memory in this structure:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
------- ------- ------- ------- ------- ---------
line 0 line 1 line 2 line 3 line 4 line 5
----------------------- -------------------------
block 0 block 1
-------------------------------------------------
3D array
I am trying to learn the concept of pointers in depth. In the below code , I create an array an create a pointer to each of the element.
int bucky[5];
int *bp0 = &bucky[0];
int *bp1 = &bucky[1];
int *bp2 = &bucky[2];
cout<<"bp0 is at memory address:"<<bp0<<endl;
cout<<"bp1 is at memory address:"<<bp1<<endl;
cout<<"bp2 is at memory address:"<<bp2<<endl;
These are the memory allocations given to the array elements.
bp0 is at memory address:0x0018ff3c
bp1 is at memory address:0x0018ff40
bp2 is at memory address:0x0018ff44
With my limited knowledge in c++ , I am aware that memory is allocated contiguously to an array. But looking at the output closely, bp0 looks out of place.
According to me bp0 should be at 0x0018ff36. Or is it that the locations 0x0018ff3c , 0x0018ff40 , 0x0018ff44 are continuous in the CPU?
So is it possible that two contiguous memory allocations are not assigned in a progression?
+---+---+---+---+---+---+---+---+---+---+---+---+
| bp0 | bp1 | bp2 |
+---+---+---+---+---+---+---+---+---+---+---+---+
0x0018ff3c d e f 40 1 2 3 4 5 6 7 8
Assuming size of int is 4 bytes and as bp0 points at 0x0018ff3c.
bp1 = bp0 + 4 = 0x0018ff40
bp2 = bp1 + 4 = 0x0018ff44
Each int uses 4 bytes.
The first position of the array is 0x0018ff3c so the next int will be at 0x0018ff3c + 4
Notice the addresses are in heaxadecimal, so:
0x0018ff3c + 0x00000004 = 0x0018ff40
Note: these are all hexadecimal numbers. The order looks like this: 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41...
Suppose you have 32 threads and 32 pieces of data for each thread to operate on independently, e.g.
struct data
{
unsigned short int N;
char *features; //array length N
uint *values; //array length N
};
data alldata[32];
Suppose that the shared memory for these threads is "partitioned" into 32 "banks", where each bank is 4 bytes wide. Each thread can read from its corresponding "bank" in parallel, but if threads try to access the same bank simlutaneously, the read operation serializes.
bank | 0 | 1 | 2 | .....
bytes | 0 1 2 3 | 4 5 6 7 | 8 9 10 11 | ....
bytes | 128 129 130 131 | 132 133 134 135 | 136 137 138 139 | ...
...............
...............
threads | 0 | 1 | 2 | .....
(This bizarre situation is called GPU computing).
Thus, for maximum parallelization:
(in terms of the picture above) the member variables of alldata[0] must only be written to the bytes in the first column. The member of variables of alldata[1] to the second column, etc. Equivalently,
In other words, I must write the contents of alldata[32] into one dynamic array, where the member variables of alldata[j] are written in 4-byte intervals once every 32*4 bytes. Then, when I copy this dynamic array into the shared memory for the threads, it will be properly aligned for the banks.
Question:
Does anybody know of any kind of package that will write variables to a byte array with proper spacing, as discussed above (once every 32*4 bytes) ?
This is a desperation question...