I have read online that memmove is expected to perform no action if the number of bytes to copy is 0. However what I want to know is if it is expected that the source and destination pointers will not be read in that case
Below is a simplified version of some of my code, the section I am interested in is shiftLeft:
#include <array>
#include <cstring>
#include <iostream>
class Foo final {
unsigned just = 0;
unsigned some = 0;
unsigned primitives = 0;
};
template <unsigned Len>
class Bar final {
unsigned depth = 0;
std::array<Foo, Len> arr;
public:
Bar() = default;
// Just an example
void addFoo() {
arr[depth] = Foo();
depth++;
}
void shiftLeft(unsigned index) {
// This is what my question focuses on
// If depth is 10 and index is 9 then index + 1 is out of bounds
// However depth - index - 1 would be 0 then
std::memmove(
&arr[index],
&arr[index + 1],
(depth - index - 1) * sizeof(Foo)
);
depth--;
}
};
int main() {
Bar<10> bar;
for (unsigned i = 0; i < 10; ++i)
bar.addFoo();
bar.shiftLeft(9);
return 0;
}
When Len is 10, depth is 10, and index is 9 then index + 1 would read out of bounds. However also in that case depth - index - 1 is 0 which should mean memmove would perform no action. Is this code safe or not?
The memmove function will copy n bytes. If n is zero, it will do nothing.
The only possible issue is with this, where index is already at the maximum value for array elements:
&arr[index + 1]
However, you are permitted to refer to array elements (in terms of having a pointer point to them) within the array or the hypothetical element just beyond the end of the array.
You may not dereference the latter but you're not doing that here. In other words, while arr[index + 1] on its own would attempt a dereference and therefore be invalid, evaluating the address of it is fine.
This is covered, albeit tangentially, in C++20 [expr.add]:
When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the expression P points to element x[i] of an array object x with n elements, the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) element x[i + j] if 0 ≤ i + j ≤ n; otherwise, the behavior is undefined.
Note the if 0 ≤ i + j ≤ n clause, particularly the final ≤. For an array int x[10], the expression &(x[10]) is valid.
It's also covered in [basic.compound] (my emphasis):
A value of a pointer type that is a pointer to or past the end of an object represents the address of the first byte in memory occupied by the object or the first byte in memory after the end of the storage occupied by the object, respectively.
Related
i have 5 digits in 1 pointer
int* reversevec(int* ptr, unsigned int Ne){
int* ReverResult;
unsigned int rever=Ne, z;
ReverResult=(int*)malloc(Ne*sizeof(int));
for (int i = 0; i < Ne; ++i)
{
z=*(ptr+rever);
printf("%i ",z);//to be sure z starts from the last number on ptr to the fisrt
rever--;
}
return ReverResult;
}
example
Number of elements(Ne)=5
int* ptr have 5 numbers {1 2 3 4 5}
every time when z is printed i got {5 4 3 2 1}
but i cant save z into *ReverResult
ReverResult=(z+rever);
this line is what i tried to put into cicle for to save z and position into int pointer ReverResult but i cant convert int to int*;
There are many problems here
z is a local variable int.
its address will not be useful to return, because it will be out of scope.
returning an offset from its address is even worse, since that is a totally unrelated place in memory.
you also have an off-by-one error. imagine Number elements is one. You will then try to view ptr+1 instead of ptr+0.
you've also tagged this c++ but are writing c style code.
to answer your primary question, rather than writing ReverResult=(z+rever) one could write *(ReverResult + rever - 1) = *(ptr + i)
The other way round, you need to dereference your pointer to be able to assign. After all, you are easier off with pure pointer arithmetics:
int* result = malloc(sizeof(*ptr) * ne);
// let's just have to pointers running through the two arrays:
for(int* p = ptr + ne, *r = result; p-- != ptr; ++r)
{
*r = *p;
// ^ ^ this is the important part: dereference both pointers
}
If you still prefer indices you can use operator[]:
--ne; // so that we don't have to subtract within the loop again and again
for(size_t index = 0; index <= ne; ++index)
{
result[index] = ptr[ne - index];
// ^^^^^^^ again: dereferencing, this time with offset
}
array[index] is entirely equivalent to *(array + index) – and actually it, too, to index[array] (e. g. 7[array]), which is often used to fool the inexperienced...
#include<iostream>
using namespace std;
int main(){
int arr[] = {1,2,3};
printf("outside loop trail 1: arr[-1] = %d \n", arr[-1]);
for(int i = 0; i<10; i++){
printf("\ninside loop trail i = %d, arr[-1] = %d \n", i, arr[-1]);
}
}
Question:
Why the output inside the loop is the sequence 0, 1, 2 (same as the loop index i); but the output outside the loop changes every time I execute the code? Thanks!
Output after
g++ -o explore explore.cpp && ./explore
outside loop trail 1: arr[-1] = 537839344
inside loop trail i = 0, arr[-1] = 0
inside loop trail i = 1, arr[-1] = 1
inside loop trail i = 2, arr[-1] = 2
run ./explore for a second time:
outside loop trail 1: arr[-1] = 1214220016
inside loop trail i = 0, arr[-1] = 0
inside loop trail i = 1, arr[-1] = 1
inside loop trail i = 2, arr[-1] = 2
This is actually covered in the standard. For example, C++17 [expr.add] /4 states:
When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the expression P points to element x[i] of an array object x with n elements, the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) element x[i + j] if 0 <= i + j <= n; otherwise, the behavior is undefined.
The reason I'm discussing adding pointers and integers is because of the equivalence of array[index] and *(array + index), as per C++17 [expr.sub] /1 (that's sub as in subscripting, not subtraction):
The expression E1[E2] is identical (by definition) to *((E1)+(E2)).
Now that's a lot to take in but it basically means that the result of adding a 'pointer to array element' and an 'index', gives you a pointer that is required to point to either an element in the array or just beyond the last one(1).
Since a pointer before the first one (array[-1]) does not meet that requirement, it's undefined behaviour. Once you do that, all bets are off and the implementation is free to do what it likes. You can count yourself lucky it didn't erase your hard disk after playing derisive_laughter.ogg :-)
Note that there's nothing wrong per se with a negative index, the following code gives you the second element (the final "pointer" is still within the array):
int array[100];
int *ptrThird = &(array[2]);
int second = ptrThird[-1];
(1) Note that a pointer is allowed to point just beyond the array provided you don't try to dereference it. Unfortunately, array[index] is a dereferncing operation so, while int array[10]; int *p = &(array[10]); is valid, int x = array[10]; is not.
This is an undefined behavior.
Generally speaking, an array index used this way is equivalent to doing pointer math thusly:
arr[n] -> *(arr+n)
By using a negative index, you are referencing memory before the start of the memory block associated with the array data. If you use an index that is outside the bounds of the array, the result is, as others have pointed out, undefined.
expr.sub/1:
A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall be a glvalue of type “array of T” or a prvalue of type “pointer to T” and the other shall be a prvalue of unscoped enumeration or integral type. The result is of type “T”. The type “T” shall be a completely-defined object type. The expression E1[E2] is identical (by definition) to *((E1)+(E2)), except that in the case of an array operand, the result is an lvalue if that operand is an lvalue and an xvalue otherwise. The expression E1 is sequenced before the expression E2.
expr.add/4:
When an expression J that has integral type is added to or subtracted from an expression P of pointer type, the result has the type of P.
(4.1) If P evaluates to a null pointer value and J evaluates to 0, the result is a null pointer value.
(4.2) Otherwise, if P points to element x[i] of an array object x with n elements, the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) element x[i + j] if 0 ≤ i + j ≤ n and the expression P - J points to the (possibly-hypothetical) element x[i - j] if 0 ≤ i − j ≤ n.
(4.3) Otherwise, the behavior is undefined.
I'm using a dynamic array to implement my stack. I wrote pop as the following:
int pop() {
int n = arr[--arr.length];
return n;
}
Using above code I get an Range violation error at run-time. But using the following code:
int pop() {
int n = arr[arr.length - 1];
arr.length--;
return n;
}
It works fine. I don't understand why, to me both should be equivalent. What am I missing?
EDIT:
maybe is this why --arr.length cause element I'm going to access be "removed" from array?
Also, push(N) is just arr ~= n;
You're removing the element before you grab it. You have to retrieve the element, and then reduce the size of the array.
--arr.length is reducing the length of the array, and then returning the new reduced size. You then attempt to do int n = arr[arr.length].
Here's a simple work-through of int n = arr[ --arr.length ] with one element:
arr.length = 1
last element is at position 0
evaluate --arr.length
arr is reduced to zero elements
arr.length returns 0
evaluate int n = arr[0].
arr is empty, breaks.
It is known that two- and one-dimensional arrays can be used equivalently, by simple coordinate conversion. Is such equivalence guaranteed by the C++ standard, or maybe it's the most convenient way of organizing data, but doesn't have to be obeyed everywhere?
For example, is the following code compiler-independent?
std::ofstream ofbStream;
ofbStream.open("File", std::ios::binary);
char Data[3][5];
for(int i=0; i<3; ++i)
for(int j=0; j<5; ++j)
{
Data[i][j] = (char) 5*i+j;
}
ofbStream.write(&Data[0][0], 15);
ofbStream.close();
The program is expected to write the numbers: 0, 1, 2, ..., 14 to a file.
In practice, this is just fine. Any compiler that doesn't do that would have countless problems with existing code.
Very strictly speaking, though, the pointer arithmetic needed is Undefined Behavior.
char Data[3][5];
char* p = &Data[0][0];
p + 7; // UB!
5.7/5 (emphasis mine):
When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that that difference of the subscripts of the resulting and original array elements equals the integral expression. ... If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
The Standard does guarantee that all the array elements are adjacent in memory and are in a specific order, and that dereferencing a pointer with the correct address (no matter how you got it) refers to the object at that address, but it doesn't guarantee that p + 7 does anything predictable, since p and p + 7 don't point at elements of the same array or past-the-end. (Instead they point at elements of elements of the same array.)
In his book The C++ Programming Language, Bjarne Stroustrup mentions (C.7.2; p. 838 of the Special Edition, 2000):
... We can initialize ma like this:
void int_ma() {
for(int i=0; i<3; i++)
for(int j=0; j<5; j++) ma[i][j] = 10 * i + j; }
...
The array ma is simply 15 ints that we access as if it were 3
arrays of 5 ints. In particular, there is no single object in memory
that is the matrix ma - only the elements are stored. The dimensions 3
and 5 exist in the compiler source only.
(emphasis mine).
In other words, the notation [][]...[] is a compiler construction; syntactical sugar if you will.
For entertainment purposes, I wrote the following code:
#include<cstdlib>
#include<iostream>
#include<iterator>
#include<algorithm>
int main() {
double ma[5][3]; double *beg = &ma[0][0]; // case 1
//double ma[3][5]; double *beg = &ma[0][0]; // case 2
//double ma[15]; double *beg = &ma[0]; // case 3
double *end = beg + 15;
// fill array with random numbers
std::generate(beg, end, std::rand);
// display array contents
std::copy(beg, end, std::ostream_iterator<double>(std::cout, " "));
std::cout<<std::endl;
return 0;
}
And compared the assembly generated for the three cases using the compilation command (GCC 4.7.2):
g++ test.cpp -O3 -S -oc1.s
The cases are called c1.s, c2.s, and c3.s. The output of the command shasum *.s is:
5360e2438aebea682d88277da69c88a3f4af10f3 c1.s
5360e2438aebea682d88277da69c88a3f4af10f3 c2.s
5360e2438aebea682d88277da69c88a3f4af10f3 c3.s
Now, I must mention that the most natural construction seems to be the one-dimensional declaration of ma, that is: double ma[N], because then the initial position is simply ma, and the final position is simply ma + N (this is as opposed to taking the address of the first element of the array).
I find that the algorithms provided by the <algorithm> C++ Standard Library header fit much more snuggly in this case.
Finally, I must encourage you to consider using std::array or std::vector if at all possible.
Cheers.
C++ stores multi-dimensional arrays in row major order as a one-dimensional array extending through memory.
As other commenters have indicated, the 2-dimensional array will be mapped to 1-dimensional memory. Is your assumption platform independent? I would expect so, but you should always test it to be sure.
#include <iostream>
#include <iterator>
#include <algorithm>
int main() {
char Data[3][5];
int count = 0;
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 5; ++j)
Data[i][j] = count++;
std::copy(&Data[0][0], &Data[0][0] + 15, std::ostream_iterator<int>(std::cout,", "));
}
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
http://www.fredosaurus.com/notes-cpp/arrayptr/23two-dim-array-memory-layout.html
How are multi-dimensional arrays formatted in memory?
Memory map for a 2D array in C
Quote
It follows from all this that arrays in C++ are stored row-wise (last subscript varies fastest) and that
the first subscript in the declaration helps determine the amount of storage consumed by an array but plays
no other part in subscript calculations.
C++ ISO standard
Assume I have a vector v with m elements in it, and a random access index to the vector called i.
When I increment the index, if it goes out of bounds, I want to index the first (zeroth) element. Similarly, when I decrement the index, if the index is < 0, I want to index to last element. At the moment I'm only moving through the container one element at a time, so came up with this function:
unsigned int GetIndexModM(int index,unsigned int m) {return (index + m) % m;}
The call-site might look like this:
std::vector<Whatever> v = ... // initialise with 5 elements
unsigned int i = 0;
unsigned int j = GetIndexModM(static_cast<int>(i) - 1,v.size()); // get preceeding index
This function will fail however if one subtracts a value > m from index:
unsigned int j = GetIndexModM(static_cast<int>(i) - 17,v.size()); // oops: returns -2
My question: What's the most elegant implementation of a function that takes any integer and returns it's place as an index?
The trick for handling MOD is this, which works with positive as well as negative numbers:
val = ((val % mod_val) + mod_val) % mod_val;
For example, assume we want to keep value between 0 and 359 inclusive. We could use this:
val = ((val % 360) + 360) % 360;
Here's a simple example in C++.
int getmod(int val, int mod) {
return ((val % mod) + mod) % mod;
}
int main() {
printf("%d\n", getmod(50,360)); // prints 50
printf("%d\n", getmod(-400,360)); // prints 320
printf("%d\n", getmod(350,360)); // prints 350
printf("%d\n", getmod(375,360)); // prints 15
printf("%d\n", getmod(-725,360)); // prints 355
return 0;
}
Unfortunately, C++ doesn’t implement a proper modulus that still works correctly for negative integers.
I think the cleanest solution is indeed using if to take care of all cases properly. This at least makes the code obvious (because every case is explicit) and errors easier to find:
unsigned GetIndexModM(int index, unsigned m) {
if (index < 0)
return GetIndexModM(index + m, m);
if (index >= m)
return index % m;
return index;
}
The following ensures that index is in [0,n) but with only one modulus operation and no branches:
index = index % n + (index < 0)*n
where the first term (containing the modulus operator) gets the value into (-n,n) and the second term ensures that the value is in [0,n).
Note that this is unreliable when n is an unsigned type and in older (pre-11) versions of C++ where the % operator is implementation dependent for negative arguments.