C++: How to get pointer to 2 dimensional dynamic array? - c++

I looked at this excellent answer but can't figure out how to apply it to this snipped:
//this is in the .hpp file
std::atomic<int> size = 10;
std::recursive_mutex *locks[2];
//in some function of the class
//it's important that the 2nd array dimension is dynamic
the_lock[0] = new std::recursive_mutex[size];
the_lock[1] = new std::recursive_mutex[size];
std::recursive_mutex (*locks_2)[2][size] = &locks;
The assignment gives me
error: cannot convert ‘std::recursive_mutex* (*)[2]’ to ‘std::recursive_mutex (*)
[2][(((sizetype)(((ssizetype)((**here be long type information, since I'm using
templates a lot**, long unsigned int, std::less<long unsigned int>
>::size.std::atomic<long unsigned
int>::<anonymous>.std::__atomic_base<_IntTp>::operator
std::__atomic_base<_IntTp>::__int_type<long unsigned int>()) + -1)) + 1)]’ in
initialization
How can I obtain a pointer to 'locks'?

The error message is actually giving away the solution for free:
std::recursive_mutex * (*locks_2)[2] = &locks;

One can use the fact that this sort of thing has been officially declared to be ridiculously hard to get right for no apparent reason that the compiler cannot solve for you. If your compiler supports C++ 2011 that is. Use:
auto my_ptr = &locks; // point to locks, let the compiler worry about types
Requires that you compile your code as C++ 2011 though. (-std=c++11 for GCC).

locks is just an array of pointers. So you could use a pointer pointer to point to it.
std::recursive_mutex **locks_2 = locks;

Related

char *test[]. What does it means this structure?

Example:
//
test.h
#define MAX 3
test.cpp
static char *movies[MAX] = {
"The Departed", "The Crow", "Hot Fuzz"};
//
Why not use Vector<char*>, or Vector<string*>, or an Array, or another data type?
What benefits do i have over the other data types?
Let me preface this by saying that i'm coming from the Java world andi've been learning C++ for a few months.
What benefits do i have over the other data types?
One thing to notice if using std::vector is that it will be initialized dynamically at runtime while the static const char*[max] can be initialized at compile time. So it will save some(very little though) runtime.
You will not have to directly cast the pointer to another type.. if some functions only accept the char ptr vector then you will not have any conversion to do

reference to an array of size determined at run-time

I tried to find this but can't find any. I know I can create a reference to an array variable:
int x[10] = {}; int (&y)[10] = x;
However, in the case that the array size is not known at compile time, like in the following code:
const int n = atoi( string ); //the string is read from a text file at run time.
int x[n] = {}; int (&y)[n] = x; //this generates a compiling error.
Even if int n is declared const, as long as n is not known at compile time, the reference is invalid. The compiler will say something like this: reference to type 'int [n]' cannot bind to a value of unrelated type 'int [n]'. Anyone has any idea about how to fix this? Thanks in advance.
Runtime-length arrays are a C99 feature and do not exist in standard C++. They're present as an extension on some C++ compilers, but don't mix well with C++ features, like references and templates.
You should probably use a vector.
The feature of declaring arrays dynamically like shouldn't be used in C++. Not all compilers support it. Consider using the STL containers instead. Like std::vector<int>

Casting Const Pointer To Work With Legacy C Code

As a follow up to my previous question (Variable Length Array Performance Implications (C/C++)), I am having a bit of trouble maintaining const correctness using the C system call writev(). Namely, it appears as though I have run into the exact same problem as this user did in C, although I am using C++:
https://codereview.stackexchange.com/questions/9547/casting-const-pointer-to-non-const-pointer-when-using-struct-iovec
Here's a snippet of my code:
int my_awesome_transmit_function(const uint8_t* const buffer, const size_t length) {
// ... some stuff happens...
struct iovec iov[2];
iov[1].iov_base = buffer; // compiler yells about this
iov[1].iov_len = length;
// ... some more code you don't care about
writev(my_fd, iov, 2);
}
Given the solution presented from the CodeReview post, I have implemented the following change to the line that's giving me issues since I'd like to avoid the C-style cast:
iov[1].iov_base = const_cast<uint8_t*>(buffer);
Is this a valid way of using const cast? As far as I can tell, writev guarentees that the iov structure will not be modified (http://linux.die.net/man/2/writev). This blog post (http://blog.aaronballman.com/2011/06/when-should-you-use-const_cast/) leads me to believe that this is a valid usage (since I am never modifying the buffer), but I'd like to be certain since generally wherever I see const_cast or reinterpret_cast, I get a bit leery.
Thanks in advance for the help.
Yes, your use of const_cast is fine.
If one of the array elements is not going to be modified (ever), then you could declare it as a const.
const struct iovec iov_c(buffer, length); // create a constructor for your struct! always neater than
// assigning their members directly in code.
This assumes you have control over the signature of writev(..) and can pass in two iovec pointers.
If not, the usage of const_cast there looks alright.

Getting the address of a member function, using CPP

I am working on a school assignment in which I need to build a thread library.
I need pc to hold the address of the given Thread object's run() function.
When I try to cast a member function pointer to address_t (which is really unsigned long int) I get this error
../main.cpp: In function ‘void setup(Thread&)’:
../main.cpp:77:22:
error: invalid cast from type ‘int (Thread::*)()’ to type ‘address_t
{aka unsigned int}’
make: * [main.o] Error 1
Here's the function where I get the error:
void setup(Thread &thread)
{
address_t sp, pc;
sp = (address_t)stack1 + STACK_SIZE - sizeof(address_t);
int (Thread::*temp)() = &Thread::run;
pc = (address_t) temp; // ## LINE 77 ##
sigsetjmp(jbuf[0],1);
(jbuf[0]->__jmpbuf)[JB_SP] = translate_address(sp);
(jbuf[0]->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&jbuf[0]->__saved_mask);
}
A few clarification:
Thread is a class I wrote, currently doing nothing. It as a int run(void) as its "main" function. address_t, as I said, is typedef unsigned long int
Any ideas as to why I get this error? thanks
I don't think you can do that.
void pointers are pointers to data, and function pointers point to functions. The language does not require functions and data to be in the same address space, so, by way of example and not limitation, on architectures that have them in different address spaces, the two different pointer types will not be comparable.
Take a look at this nice faq. If you cannot convert to void*, then you cannot convert to int or long int
This doesn’t work for two reasons:
function pointers are not compatible with void* (se UmNyobe’s answer), and
in order to use member functions as the thread entry you’d need to store a this pointer as well.
Since you’re using C++ you’ve got a few possibilities though:
Use a base class thread_base defining a virtual function as the thread entry point.
Use a functor as the thread entry point.
In either case you’d need to store this information somewhere and invoke it using the operating system’s thread library.

use array in structure c++

I have a struc like this:
struct process {int PID;int myMemory[];};
however, when I try to use it
process p;
int memory[2];
p.myMemory = memory;
I get an criptic error from eclipse saying int[0] is not compatible with int[2];
what am i doing wrong?
Thanks!
Don't use static arrays, malloc, or even new if you're using C++. Use std::vector which will ensure correct memory management.
#include <vector>
struct Process {
int pid;
std::vector<int> myMemory;
};
Process p;
p.reserve(2); // allocates enough space on the heap to store 2 ints
p.myMemory.push_back( 4815 ); // add an index-zero element of 4815
p.myMemory.push_back( 162342 ); // add an index-one element of 162342
I might also suggest creating a constructor so that pid does not initially have an undefined value:
struct Process {
Process() : pid(-1), myMemory() {
}
int pid;
std::vector<int> myMemory;
};
I think you should declare myMemory as an int* then malloc() when you know the size of it. After this it can be used like a normal array. Int[0] seems to mean "array with no dimension specified".
EXAMPLE:
int *a; // suppose you'd like to have an array with user specified length
// get dimension (int d)
a = (int *) malloc(d * sizeof(int));
// now you can forget a is a pointer:
a[0] = 5;
a[2] = 1;
free((void *) a); // don't forget this!
All these answers about vector or whatever are confused :) using a dynamically allocated pointer opens up a memory management problem, using vector opens up a performance problem as well as making the data type a non-POD and also preventing memcpy() working.
The right answer is to use
Array<int,2>
where Array is a template the C++ committee didn't bother to put in C++99 but which is in C++0x (although I'm not sure of the name). This is an inline (no memory management or performance issues) first class array which is a wrapper around a C array. I guess Boost has something already.
In C++, array definition is almost equal to pointer constants, meaning that their address cannot be changed, while the values which they point to can be changed. That said, you cannot copy elements of an array into another by the assignment operator. You have to go through the arrays and copy the elements one by one and check for the boundary conditions yourself.
The syntax ...
struct process {int PID;int myMemory[];};
... is not valid C++, but it may be accepted by some compilers as a language extension. In particular, as I recall g++ accepts it. It's in support for the C "struct hack", which is unnecessary in C++.
In C++, if you want a variable length array in a struct, use std::vector or some other array-like class, like
#include <vector>
struct Process
{
int pid;
std::vector<int> memory;
};
By the way, it's a good idea to reserve use of UPPERCASE IDENTIFIERS for macros, so as to reduce the probability of name collisions with macros, and not make people reading the code deaf (it's shouting).
Cheers & hth.,
You cannot make the array (defined using []) to point to another array. Because the array identifier is a const pointer. You can change the value pointed by the pointer but you cannot change the pointer itself. Think of "int array[]" as "int* const array".
The only time you can do that is during initialization.
// OK
int array[] = {1, 2, 3};
// NOT OK
int array[];
array = [1, 2, 3]; // this is no good.
int x[] is normally understood as int * x.
In this case, it is not, so if you want a vector of integers of an undetermined number of positions, change your declaration to:
struct process {int PID;int * myMemory;};
You should change your initialization to:
int memory[2];
p.myMemory = new int[ 10 ];