Given: (In C++)
int main () {
int* ptr;
int ary [10][2];
ptr = ary;
return 0;
}
How would I access ary[0][1] with ptr?
You can't, because the type of ptr is wrong. The variable should be declared as int(*)[2] (pointer to an array of size 2 of integers). Then you could just use ptr[0][1].
#include <cstdio>
int main () {
int (* ptr) [2]; // <--
int ary [10][2];
ptr = ary;
ary[0][1] = 5;
printf("%d\n", ptr[0][1]);
return 0;
}
If you must use an int*, you need to introduce a reinterpret_cast. The array indices are laid out like:
0 1 2 3 2*n 2*n+1
[0][0] [0][1] [1][0] [1][1] ... [n][0] [n][1]
so you could use ptr[1] to get ary[0][1].
#include <cstdio>
int main () {
int* ptr;
int ary [10][2];
ptr = reinterpret_cast<int*>(ary); // <--
ary[0][1] = 5;
printf("%d\n", ptr[1]);
return 0;
}
typedef int tenints[10]; // tenints is an array of 10 ints
int main () {
tenints ary[2]; // array of 2 tenints, same as your int ary[10][2];
tenints* ptr = ary
// ptr[0] or *ptr is the first row
// ptr[1] or *(ptr+1)is the second row
int* ptr2 = ptr[0];
// ptr2[1] or *(ptr2+1) is ary[0][1]
// if you don't want do use as intermediate variable,
// just substitute "*ptr" for "ptr2" in "*(ptr2+1)"
int val = *((*ptr)+1);
return 0;
}
What you want only works when the data is on block which it might not be in all cases. In the context of image processing, you mostly do something like this:
int width = 1024;
int height = 768;
char* img = new char[width*height];
char** img2d = new char*[height];
for (int y = 0; y < height; ++y){
img2d[y] = img + y*width;
}
//set pixel at x=50, y=100
img2d[100][50] = 1;
//does the same
img2d[100*width+50] = 1;
delete[] img;
it is possible, just look at this example ( these are dynamic arrays, but works with static too ):
void bla ( void )
{
const int32_t sx = 50, sy = 30, sz = 50;
uint64_t *** n = NULL;
n = ( uint64_t*** )malloc( sizeof( uint64_t** ) * sx );
for ( int32_t x = 0; x < sx; x++ )
{
*( n + x ) = ( uint64_t** )malloc( sizeof( uint64_t* ) * sy );
for ( int32_t y = 0; y < sy; y++ )
*( *( n + x ) + y ) = ( uint64_t* )malloc( sizeof( uint64_t ) * sz );
}
for ( int32_t x = 0; x < sx; x++ )
for( int32_t y = 0; y < sy; y++ )
for( int32_t z = 0; z < sz; z++ )
*( *( *( n + x ) + y ) + z ) = 1024 * 1024;
}
Related
I have a pointer that points to the beginning of a 1000+ elements array that is initialized as below:
int numElements = 1200;
auto data = std::unique_ptr<float>{new float[numElements]};
Now I want to 'reshape' it into something like a (20,30,20) tensor, so I can access it the way I want (I can still read while it's 1-D as well but it feels weird). I want to access like this:
data[1][10][12] = 1337.0f;
Is there an efficient way of doing this (fast and short code)?
In the meantime, this is how I do it...
#include <iostream>
using std::cout;
using std::endl;
#include <vector>
using std::vector;
size_t get_index(const size_t x, const size_t y, const size_t z, const size_t x_res, const size_t y_res, const size_t z_res)
{
return z * y_res * x_res + y * x_res + x;
}
int main(void)
{
const size_t x_res = 10;
const size_t y_res = 10;
const size_t z_res = 10;
// Use new[] to allocate, and memset to clear
//float* vf = new float[x_res * y_res * z_res];
//memset(vf, 0, sizeof(float) * x_res * y_res * z_res);
// Better yet, use a vector
vector<float> vf(x_res*y_res*z_res, 0.0f);
for (size_t x = 0; x < x_res; x++)
{
for (size_t y = 0; y < y_res; y++)
{
for (size_t z = 0; z < z_res; z++)
{
size_t index = get_index(x, y, z, x_res, y_res, z_res);
// Do stuff with vf[index] here...
}
}
}
// Make sure to deallocate memory
// delete[] vf;
return 0;
}
This code should output 0 0.25 0.5 0.75 1, instead it outputs zeros. Why is that?
Define a function u(x)=x;
void pde_advect_IC(double* x, double* u)
{
int N = sizeof(x) / sizeof(x[0]); //size of vector u
for (int i = 0; i <= N; i++)
u[i] = x[i];
}
Here is the implementation:
int main()
{
double a = 0.0;
double b = 1.0;
int nx = 4;
double dx = (b - a) / double(nx);
double xx[nx + 1]; //array xx with intervals
// allocate memory for vectors of solutions u0
double* u0 = new double [nx + 1];
//fill in array x
for (int i = 0; i <= nx; i++)
xx[i] = a + double(i) * dx;
pde_advect_IC(xx, u0); // u0 = x (initial conditions)
for (int i = 0; i <= nx; i++)
cout<<u0[i]<<endl;
// de-allocate memory of u0
delete [] u0;
delete [] u1;
return 0;
}
You can't use sizeof(x) because that will return the size of the pointer, not the array you thought you passed to it. You have to specify the size with a third parameter or use something more convenient like an std::vector and use size().
This works.
#include <iostream>
#include <cstdlib>
using namespace std;
void pde_advect_IC(double* x, double* u, const int& N)
{
for (int i = 0; i < N; i++)
u[i] = x[i];
}
int main()
{
double a = 0.0;
double b = 1.0;
int nx = 4;
double dx = (b - a) / double(nx);
double xx[nx + 1]; //array xx with intervals
// allocate memory for vectors of solutions u0
double* u0 = new double [nx + 1];
//fill in array x
for (int i = 0; i <= nx; i++)
xx[i] = a + double(i) * dx;
pde_advect_IC(xx, u0, nx + 1); // u0 = x (initial conditions)
for (int i = 0; i <= nx; i++)
cout << u0[i] << endl;
// de-allocate memory of u0
delete [] u0;
return 0;
}
Note that I added const int& N to pde_advect_IC() in order to pass it the size of the array, by const reference, to be sure it does not get modified by mistake.
Note that your trick with sizeof() does not work with pointers.
Hello guys, I've a map_server that reads in a PGM file yet prints out a flipped image of it on a QImage.
Here is my code.
int width = msg->info.width;
int height = msg->info.height;
const std::vector<int8_t>& data (msg->data);
unsigned char *p, *q;
if( mapImage == NULL ) {
lineImage = new unsigned char[ width * 3 ];
mapImage = new QImage( width, height, QImage::Format_RGB888 );
}
if( mapImage != NULL ) {
for( int i = 0; i < height; i++ ) {
q = lineImage;
p = ( unsigned char * )&data[ i * width ];
for( int j = 0; j < width; j++ ) {
*q++ = *p;
*q++ = *p;
*q++ = *p;
p++;
}
memcpy( mapImage->scanLine( i ), lineImage, width * 3 );
}
}
printf( "Map received!\n" );
The "for loop" for height takes in from "0" till the limit(height) and I can assume that the picture it reads in the limit, till "0".
I can't provide Images due to the reputation. But I still hope I could garner some help in this...
Thanks!
JeremyEthanKoh.
When converting between JPG and BMP scan lines are inverted in Y. This is specific to the BMP format. It seems that your QImage is a RGB 24-bil bitmap and you directly write in its pixel map line by line. Just reverse the scanlines in Y:
if( mapImage != NULL ) {
for( int i = 0; i < height; i++ ) {
q = lineImage;
p = ( unsigned char * )&data[ i * width ];
for( int j = 0; j < width; j++ ) {
*q++ = *p;
*q++ = *p;
*q++ = *p;
p++;
}
memcpy( mapImage->scanLine( height-i-1 ), lineImage, width * 3 );
}
}
I have a struct that defines a 3d array, the size is known:
struct uchar3
{
unsigned char x, y, z;
};
and I want to return it via mex function in order to use it in matlab like a three dimensional array, like an image. How can this be done?
EDIT:
This is apart of the function I use.
foo(uchar3 **imagePtr, Mat Im){
unsigned char *cvPtr = Im.ptr<unsigned char>(0);
for (size_t i = 0; i < Im.rows * Im.cols; ++i) {
(*imagePtr)[i].x = cvPtr[3 * i + 0];
(*imagePtr)[i].y = cvPtr[3 * i + 1];
(*imagePtr)[i].z = cvPtr[3 * i + 2];
}
}
Shai's code:
cv::Mat imageRGB;
cv::cvtColor(OutPutMat, imageRGB, CV_BGR2RGB);
// uc3 is populated here
mwSize sz[3];
sz[0] = imageRGB.rows; // matlab is row first
sz[1] = imageRGB.cols;
sz[2] = 3;
plhs[0] = mxCreateNumericArray( 3, sz, mxDOUBLE_CLASS, // create double array, you can change the type here
mxREAL ); // create real matrix
float *cvPtr = imageRGB.ptr<float>(0);
float* p = (float*)mxGetData(plhs[0]); // get a pointer to actual data
for ( size_t y = 0 ; y < imageRGB.rows ; y++ ) {
for ( size_t x = 0; x < imageRGB.cols ; x++ ) {
int i = y * imageRGB.cols + x; // opencv is col first
p[ x * imageRGB.rows + y ] = cvPtr[3 * i + 0];
p[ imageRGB.cols * imageRGB.rows + x * imageRGB.rows + y ] = cvPtr[3 * i + 1];
p[ 2*imageRGB.cols * imageRGB.rows + x * imageRGB.rows + y ] = cvPtr[3 * i + 2];
}
}
You need to use mxCreateNumericArray
uchar3 uc3;
// uc3 is populated here
mwSize sz[3];
sz[0] = Im.rows; // matlab is row first
sz[1] = Im.cols;
sz[2] = 3;
mxArray* pOut = mxCreateNumericArray( 3, sz, mxDOUBLE_CLASS // create double array, you can change the type here
mxREAL ); // create real matrix
double* p = (double*)mxGetData(pOut); // get a pointer to actual data
for ( size_t y = 0 ; y < Im.rows ; y++ ) {
for ( size_t x = 0; x < Im.cols ; x++ ) {
int i = y * Im.cols + x; // opencv is col first
p[ x * Im.rows + y ] = cvPtr[3 * i + 0];
p[ Im.cols*Im.rows + x * Im.rows + y ] = cvPtr[3 * i + 1];
p[ 2*Im.cols*Im.rows + x * Im.rows + y ] = cvPtr[3 * i + 2];
}
}
// set one of your mexFunction's outputs to pOut
Into your mex function do this :
plhs[0] = valueStruct(Test,Test2);
Where ValueStruct is a function
mxArray* valueStruct(const double& d,const double& d2)
{
mxArray* p = mxCreateStructMatrix(1,1,2,_fieldnames);
if (!p)
mexErrMsgIdAndTxt("error","Allocation error");
mxSetField(p,0,"d",mxArray(d));
mxSetField(p,0,"d2",mxArray(d2));
return p;
}
You can refer to mxCreateStructMatrix documentation for more informations.
And for mxSetField.
For an example, You can refer to mexopencv that create struct with his mxArray class where you can get here.
I am trying to sort an array of char pointers (char * _string) by swapping pointers.
I have this method, and what I want to do is use the values I get from _string and sort them by not manipulating _string, but the empty helper array (char * _output) which I also hand over to the method.
Can anyone help me and tell me what I am doing wrong?
void sortAsc(char* _string, char* _output)
{
int length = strlen(_string);
// output and string now point to the same area in the memory
_output = _string;
for( int i = 0; i < length; i++) {
for( int j = 0; j < length; j++) {
if( *(_output) > (_output[j] ) ) {
// save the pointer
char* tmp = _output;
// now output points to the smaller value
_output = _output+j;
// move up the pointer to the smaller value
_output + j;
// now the pointer of the smaller value points to the higher value
_output = tmp;
// move down to where we were + 1
_output - j + 1;
}
}
}
//_output[length]='\0';
//delete chars;
}
In my main-Method, I do something like this:
char * string = {"bcdae"};
char * output = new char[5];
sortAsc(string, output);
After that code, I want the output array to contain the sorted values.
Let's do the selection sort for a 10 size int array using pointer notation, you can simply change it to an array list.
*---*---*---*---*---* ........
a[] = | 1 | 2 | 4 | 0 | 3 | ........
*---*---*---*---*---* ........
^--------We start here looking for the smaller numbers and sort the array.
for( i = 0; i < 10; i++ ){
k = i;
bypass = *( a + i );
for( j = i + 1; j < 10; j++ ){
/* To get Increasing order. */
if( bypass > *( a + j ) ){
bypass = *( a + j );
k = j;
}
}
if ( k != i ){
*( a + k ) = *( a + i );
*( a + i ) = bypass;
}
}
This sorts the string into an already allocated buffer, and if the buffer isn't large enough tells you how big it has to be:
std::size_t sortAsc(char const* string, char* dest, std::size_t dest_length) {
std::size_t str_length = strlen(string);
char const* str_end = string + str_length;
if (dest_length < str_length+1)
return str_length+1;
std::copy( string, str_end, output );
output[str_length] = '\0';
std::sort( output, output+strlen(output) );
return str_length+1;
}
This does the poor "allocate a new string" pattern, using the above implementation:
char* allocate_and_sortAsc(char const* string) {
std::size_t str_length = strlen(string);
char* retval = new char[str_length+1];
std::size_t count = sortAsc( string, retval, str_length+1);
ASSERT( count <= str_length );
return retval;
}
And don't use variable names that start with an _, it is a bad practice because it wanders really near compiler reserved names. _Capital is reserved everywhere, and _lower in global scope, and foo__bar everywhere.