Is it safe to iterate a pointer to the next blob of data in C?
Is it then true or false to assume that iterating the pointer to any of those structs as a struct Header pointer will result in the address of the next member of that struct?
It is not safe to make such an assumption. C implementations are allowed to put arbitrary amounts of padding between struct members (in a manner that is consistent for any given struct type). Thus, roughly speaking, your function could produce a pointer to padding, rather than a pointer to the member following the header.
And how do the C data alignment requirements come and play in such scenarios? (Can eventual slop lead to bad pointers when casting for example?)
C implementations typically use alignment requirements in determining how much padding, if any, to insert between members, but the standard does not require them to do so, nor in general does it constrain how implementations make that decision.
How to check whether iterators form a contiguous memory zone?
Leaving aside your sample function, you can never be completely sure that iterators will form a contiguous memory without checking the address of every element between the two.
A reasonable sanity test, though, would be to just check if the memory area between the two is the same as the count between the two:
assert(&*last - &*first == last - first &&
"Iterators must represent a contiguous memory region");
int pointer to the .end() of a list
To implement begin()
and end()
in a style similar to STL return iterator
s, not pointers:
template <typename value_type>
class my_list
{
public:
typedef std::list<value_type>::iterator iterator;
typedef std::list<value_type>::const_iterator const_iterator;
iterator begin() { return listofValues.begin(); }
const_iterator begin() const { return listofValues.begin(); }
iterator end() { return listofValues.end(); }
const_iterator end() const { return listofValues.end(); }
};
Using other methods on a structure inside a `for` loop over an iterator which can mutate this structure
This is possibly bug #8372 caused by the minimum-that-works implementation of the current for
. It is implemented as a macro such that
for pattern in iterator { body }
expands to (you can see this by running rustc --pretty expanded foo.rs
)
{
let it = &mut iterator;
loop {
match it.next() {
None => break,
Some(pattern) => { body }
}
}
}
The problem is the &mut iterator
borrow, which stops iterator
being used directly while it
is in scope. You can normally work around this by manually writing the expansion yourself:
impl<'a> SomeTrait for &'a mut SomeStructure<'a> {
fn do_something(self) {
let mut it = self.iter();
loop {
match it.next() {
None => break
Some(e) => {
if self.test_something() {
break;
}
}
}
}
}
}
That said... this may not actually work in this case if self.iter()
borrows self
(especially if test_something
takes &mut self
, since the compiler has to disallow mutation or the iterator could be invalidated).
If you were to add a .view_creator()
method to the return of self.iter()
(assuming you have a reference to self
in the self.iter()
type) then it.view_creator().test_something()
would work (with the manually unwrapped for loop).
(FWIW, it's a little peculiar to have a trait taking self
and implementing it on &mut Thing
rather than taking &mut self
and implementing it straight on Thing
; although there are good reasons for it sometimes.)
How are random access iterators for non-contiguous containers (such as std::deque) implemented?
You can satisfy the requirememts of a std::deque
with a std::vector<std::unique_ptr<std::array<T,N>>>
roughly. plus a low/high water mark telling you where the first/last elements are. (for an implementation defined N that could vary with T
, and the std::array
s are actually blocks of properly aligned uninitialized memory and not std::array
s, but you get the idea).
Use usual exponential growth, but on both front and back.
Lookup simply does (index+first)/N
and %N
to find the block and sub element.
This is more expensive than a std::vector
lookup, but is O(1).
what is the difference between const_iterator and iterator?
There is no performance difference.
A const_iterator
is an iterator that points to const value (like a const T*
pointer); dereferencing it returns a reference to a constant value (const T&
) and prevents modification of the referenced value: it enforces const
-correctness.
When you have a const reference to the container, you can only get a const_iterator
.
Edited: I mentionned “The const_iterator
returns constant pointers” which is not accurate, thanks to Brandon for pointing it out.
Edit: For COW objects, getting a non-const iterator (or dereferencing it) will probably trigger the copy. (Some obsolete and now disallowed implementations of std::string
use COW.)
Printing the value of an int Pointer
One problem is likely to be this line:
pointerlist.push_back((&*listOfValues.begin() + endptr));
Your listOfValues
is a std::list
, and therefore its values are not stored in a contiguous block of memory. So you're getting an iterator to the first element with listOfValues.begin()
, dereferencing the iterator with *
, taking the address of that with &
to get an int*
, then adding some value which points somewhere off into memory that you don't know what it is.
Try doing this instead:
pointerlist.push_back((&*(listOfValues.begin() + endptr)));
where you add endptr
to the iterator (to advance it along the list), then dereference and take the address. Actually you may need to use advance
instead of +
.
How do function pointers in C work?
Function pointers in C
Let's start with a basic function which we will be pointing to:
int addInt(int n, int m) {
return n+m;
}
First thing, let's define a pointer to a function which receives 2 int
s and returns an int
:
int (*functionPtr)(int,int);
Now we can safely point to our function:
functionPtr = &addInt;
Now that we have a pointer to the function, let's use it:
int sum = (*functionPtr)(2, 3); // sum == 5
Passing the pointer to another function is basically the same:
int add2to3(int (*functionPtr)(int, int)) {
return (*functionPtr)(2, 3);
}
We can use function pointers in return values as well (try to keep up, it gets messy):
// this is a function called functionFactory which receives parameter n
// and returns a pointer to another function which receives two ints
// and it returns another int
int (*functionFactory(int n))(int, int) {
printf("Got parameter %d", n);
int (*functionPtr)(int,int) = &addInt;
return functionPtr;
}
But it's much nicer to use a typedef
:
typedef int (*myFuncDef)(int, int);
// note that the typedef name is indeed myFuncDef
myFuncDef functionFactory(int n) {
printf("Got parameter %d", n);
myFuncDef functionPtr = &addInt;
return functionPtr;
}
Is vector in c++ a pointer?
Is vector in c++ a pointer?
No. std::vector
is not a pointer. It is a class.
So is v a pointer that points to the start of the vector?
No, but v
(an instance of the vector class) does happen to contain a pointer to the start of the array.
why can't I access
*v
?
Because there is no overload for the unary operator*
for the class std::vector
.
Related Topics
Std::Vector Reserve() and Push_Back() Is Faster Than Resize() and Array Index, Why
Should I Use Public or Private Variables
Using Declaration in Variadic Template
C++ Trying to Swap Values in a Vector
Why Was Pair Range Access Removed from C++11
Vc++ Fatal Error Lnk1168: Cannot Open Filename.Exe for Writing
Broken C++ Std Libraries on MACos High Sierra 10.13
How to Track Memory Allocations in C++ (Especially New/Delete)
Calling a Function Through Its Address in Memory in C/C++
How to Effectively Kill a Process in C++ (Win32)
C++ View Types: Pass by Const& or by Value
Qt - Remove All Widgets from Layout
C++, How to Statically Initialize a Std::Map at Compile Time
What Is the Ndebug Preprocessor MACro Used for (On Different Platforms)
Pure/Const Function Attributes in Different Compilers
Pointer to Array of Unspecified Size "(*P)[]" Illegal in C++ But Legal in C