Rewrite C++ class in C [duplicate] - c++

This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 2 years ago.
So, I am having some trouble rewriting a C++ class I made in C.
The C++ class has some private attributes:
int grid_width;
int grid_height;
const int group_width = 2;
const int group_height = 4;
std::vector<int> buffer;
It is initialized like so:
grid::grid(int width, int height) {
this->grid_width = width;
this->grid_height = height;
buffer.resize(this->grid_width / this->group_width * this->grid_height / this->group_height, 0);
}
It also comes with a clear function like so:
void grid::clear() {
// get_buffer_size returns elements in the buffer vector
for (int i = 0; i < get_buffer_size(); ++i) {
buffer[i] = 0x00;
}
}
Now, my attempt to rewrite this in C looks somewhat like this:
typedef struct
{
int width;
int height;
int *buffer;
} grid;
grid *grid_new(int grid_width, int grid_height)
{
if ((grid_width % 2 != 0) || (grid_height % 4 != 0))
return NULL;
int group_height = 4;
int group_width = 2;
grid *p_grid = calloc(grid_width / group_width * grid_height / group_height, sizeof(int));
p_grid->width = grid_width;
p_grid->height = grid_height;
return p_grid;
}
void grid_free(grid *p_grid)
{
free(p_grid->buffer);
free(p_grid);
}
void grid_clear(grid *g)
{
// ToDo: Iterate over all elements in the buffer
int elements = sizeof(g->buffer) / sizeof(int);
printf("Elements: %i", elements);
}
But for some reason, the amount of elements in my C code is always 2?
Does anyone know where I am messing up?
If the grid is initialized with 4 and 8, the expected buffer size should be 4, not 2. If it would be initialized with 10 and 24, the expected size would be 30, but it still remains 2 in my C example.

Your grid_new is allocating an array of grid structs and not a single grid with the correct number of elements.
You need to set buffer
Also, the number of elements in the grid is based on width/height and not sizeof(g->buffer) which is the size of the pointer and not the area to which it points
Here's the refactored code:
const int group_height = 4;
const int group_width = 2;
typedef struct {
int width;
int height;
int *buffer;
} grid;
grid *
grid_new(int grid_width, int grid_height)
{
if ((grid_width % 2 != 0) || (grid_height % 4 != 0))
return NULL;
grid *p_grid = calloc(1,sizeof(*p_grid));
// FIXME -- why???
grid_width /= group_width;
grid_height /= group_height;
p_grid->width = grid_width;
p_grid->height = grid_height;
p_grid->buffer = calloc(grid_width * grid_height,sizeof(int));
return p_grid;
}
void
grid_free(grid *p_grid)
{
free(p_grid->buffer);
free(p_grid);
}
void
grid_clear(grid *g)
{
// ToDo: Iterate over all elements in the buffer
int elements = g->width * g->height;
printf("Elements: %i", elements);
}

'sizeof' returns the number of bytes that specified type takes. in this case sizeof(g->buffer) is equal to sizeof(int*) and because you are using x64 processor sizeof all pointers is 8.

Related

How to perform component labelling in a .bmp(binary image) containing digits 9 4 3 6?

I have a binary BMP image of size 284x1280. The image contains the digits 9 4 3 6. I want to perform component labelling on the image and mark the labels whenever the digits occur. Initially, it is a binary image with only 0 and 1 in the 2D array (0 marked as background and 1 marked as the digits)
I tried to write a component labelling function (checking 8 neighbours) and incrementing a counter whenever I find a component labelled 1:
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>
int func(int w, int h, int a[][1280], int i, int j, int c)
{
if(i==h||j==w)
{
return 0;
}
if(a[i][j+1]==1)
{
a[i][j+1]=c; return func(w,h,a,i,j+1,c);
}
if(a[i+1][j]==1)
{
a[i+1][j]=c; return func(w,h,a,i+1,j,c);
}
if(a[i+1][j+1]==1)
{
a[i+1][j+1]=c; return func(w,h,a,i+1,j+1,c);
}
else
{
return 0;
}
}
unsigned char* read_bmp(char *fname, int* _w, int* _h)
{
unsigned char head[54];
FILE *f=fopen(fname,"rb");
//BMP header is 54 bytes
fread(head,1,54,f);
int w=head[18]+(((int)head[19]) << 8)+(((int)head[20]) << 16)+
(((int)head[21]) << 24);
int h=head[22]+(((int)head[23]) << 8)+(((int)head[24]) << 16)+
(((int)head[25]) << 24);
//lines are aligned on 4-byte boundary
int lineSize = (w / 8 + (w / 8) % 4);
int fileSize=lineSize * h;
unsigned char *img, *data;
img =(unsigned char*)malloc(w * h), data =(unsigned
char*)malloc(fileSize);
//skip the header
fseek(f,54,SEEK_SET);
//skip palette - two rgb quads, 8 bytes
fseek(f,8,SEEK_CUR);
//read data
fread(data,1,fileSize,f);
//decode bits
int i, j, k, rev_j;
for(j=0, rev_j=h-1;j<h;j++,rev_j--)
{
for(i=0;i<w/8;i++)
{
int fpos= j * lineSize + i, pos = rev_j * w + i * 8;
for(k=0;k<8;k++)
{
img[pos+(7-k)]=(data[fpos] >> k) & 1;
}
}
}
free(data);
*_w = w; *_h = h;
return img;
}
int main()
{
int w, h, i, j, c1=0, c2=0, c3=0, c4=0, c5=0, c6=0;
unsigned char* img=read_bmp("binary.bmp",&w,&h);
int array[h][1280];
char ch;
for(j=0;j<h;j++)
{
for(i=0;i<1280;i++)
{
array[j][i]=(int(img[j * w + i])==0);
}
}
register int c=2;
for(i=0;i<h;i++)
{
for(j=0;j<1280;j++)
{
if(array[i][j]==1)
{
array[i][j]=c;
func(w,h,array,i,j,c);
}
}
}
for(i=0;i<h;i++)
{
for(j=0;j<w;j++)
{
printf("%d",array[i][j]);
}
printf("\n");
}
return 0;
}
I am getting an array of just 0 and 2, whereas it should contain 0,2,3,4,5 labels for other digits. How to fix it?
You never increment c, hence you get stuck at label 2.
Once you fix that, you’ll notice single objects being broken up into many labels. This is because you check only 3 neighbors in your recursive function. You need to check all 8 (or 4 for 4-connected neighborhood). Yes, your recursive function must be able also to travel to the left and up to follow complex shapes.
This recursive function is very inefficient and with an object large enough it could cause a stack overflow. You could instead write a loop that propagates all along the line within the object. The best algorithms for object labeling use the union-find algorithm, I encourage you to look that up.

C++: is this a correct way to use integer variables as pointers to a function call?

I am a C++ newbie.
Context: I found this third-party snippet of code that seems to work, but based on my (very limited) knowledge of C++ I suspect it will cause problems. The snippet is as follows:
int aVariable;
int anInt = 1;
int anotherInt = 2;
int lastInt = 3;
aVariable = CHAIN(anInt, anotherInt, lastInt);
Where CHAIN is defined as follows (this is part of a library):
int CHAIN(){ Map(&CHAIN, MakeProcInstance(&_CHAIN), MAP_IPTR_VPN); }
int _CHAIN(int i, int np, int p){ return ASMAlloc(np, p, &chainproc); }
int keyalloc[16384], kpos, alloc_locked, tmp[4];
int ASMAlloc(int np, int p, alias proc)
{
int v, x;
// if(alloc_locked) return 0 & printf("WARNING: you can declare compound key statements (SEQ, CHAIN, EXEC, TEMPO, AXIS) only inside main() call, and not during an event.\xa");
v = elements(&keyalloc) - kpos - 4;
if(v < np | !np) return 0; // not enough allocation space or no parameters
Map(&v, p); Dim(&v, np); // v = params array
keyalloc[kpos] = np + 4; // size
keyalloc[kpos+1] = &proc; // function
keyalloc[kpos+2] = kpos + 2 + np; // parameters index
while(x < np)
{
keyalloc[kpos+3+x] = v[x];
x = x+1;
}
keyalloc[kpos+3+np] = kpos + 3 | JUMP;
x = ASMFind(kpos);
if(x == kpos) kpos = kpos + np + 4;
return x + 1 | PROC; // skip block size
}
int ASMFind(int x)
{
int i, j, k; while(i < x)
{
k = i + keyalloc[i]; // next
if(keyalloc[i] == keyalloc[x]) // size
if(keyalloc[i+1] == keyalloc[x+1]) // proc
{
j = x-i;
i = i+3;
while(keyalloc[i] == keyalloc[j+i]) i = i+1; // param
if((keyalloc[i] & 0xffff0000) == JUMP) return x-j;
}
i = k;
}
return x;
}
EDIT:
The weird thing is that running
CHAIN(aVariable);
effectively executes
CHAIN(anInt, anotherInt, lastInt);
Somehow. This is what led me to believe that aVariable is, in fact, a pointer.
QUESTION:
Is it correct to store a parametrized function call into an integer variable like so? Does "aVariable" work just as a pointer, or is this likely to corrupt random memory areas?
You're calling a function (through an obfuscated interface), and storing the result in an integer. It might or might not cause problems, depending on how you use the value / what you expect it to mean.
Your example contains too many undefined symbols for the reader to provide any better answer.
Also, I think this is C, not C++ code.

C++ Pointer to byte array optimization

I am currently using this approach to copy some byte values over:
for (int i = 0; i < (iLen + 1); i++)
{
*(pBuffer + i) = Image.pVid[i];
}
I would like to ask if there is a way to copy these values over in one go, perhaps by using memcopy to gain more speed.
The entire code is:
extern "C" __declspec(dllexport) int __stdcall GetCameraImage(BYTE pBuffer[], int Type, int uWidth, int uHeight)
{
CameraImage Image;
int ret;
Image.pVid = (unsigned int*)malloc(4 * uWidth*uHeight);
ret = stGetCameraImage(&Image, 1, uWidth, uHeight);
if (ret == ERR_SUCCESS)
{
int iLen = (4 * uWidth * uHeight);
for (int i = 0; i < (iLen + 1); i++)
{
*(pBuffer + i) = Image.pVid[i];
}
////print(“ImageType = %d, width = %d, height = %d”, Image.Type, Image.Width,
//// Image.Height);
////print(“First Pixel : B = %d, G = %d, R = %d”, Image.pVid[0], Image.pVid[1],
//// Image.pVid[2]);
////print(“Second Pixel : B = %d, G = %d, R = %d”, Image.pVid[4], Image.pVid[5],
//// Image.pVid[6]);
}
free(Image.pVid);
return ret;
}
Edit:
*pVid is this:
unsigned int *pVid; // pointer to image data (Format RGB32...)
The way your code is currently written, each assignment in your loop will overflow and give you some garbage value in pBuffer because you're trying to assign an unsigned int to a BYTE. On top of that, you will run off the end of the Image.pVid array because i is counting bytes, not unsigned ints
You could fix your code by doing this:
*(pBuffer + i) = ((BYTE*)Image.pVid)[i];
But that is pretty inefficient. Better to move whole words at a time, or you could just use memcpy instead:
memcpy(pBuffer,Image.pVid,iLen) //pBuffer must be at least iLen bytes long

Array Partition with pointer

I have a 20 x 20 array and need to iterate over it by reading a 4 x 4 array. I thought I could do this with pointed assignment, but it does not do much except force close
const char SOURCE[20][20];
const char **pointer;
for(int x = 0; x < 20; x+=4)
{
for(int y = 0; y < 20; y+=4)
{
pointer = (const char **)&SOURCE[x][y];
printGrid(pointer);
}
}
void printGrid(const char **grid)
{
// do something usefull
}
Just casting a pointer to a different type doesn't change the
type of what it points to (and will usually lead to undefined
behavior, unless you really know what you're doing). If you
cannot change printGrid, you'll have to create an array of
pointers on the fly:
for ( int x = 0; x < 20; x += 4 ) {
for ( int y = 0; y < 20; y += 4 ) {
char const* p4[4] =
{
source[x] + y,
source[x + 1] + y,
source[x + 2] + y,
source[x + 3] + y
};
printGrid( p4 );
}
}
A pointer to a pointer is not the same as an array of arrays.
You can however use a pointer to an array instead:
const char (*pointer)[20];
You of course need to update the printGrid function to match the type.
As for the reason why a pointer-to-pointer and an array-of-array (also often called a matrix) see e.g. this old answer of mine that shows the memory layout of the two.
Your 2D-array is of type char:
const char SOURCE[20][20];
When you are iterating through it, you can either look at the char or reference the address with a char*:
for(int x = 0; x < 20; x+=4)
{
for(int y = 0; y < 20; y+=4)
{
printGrid(SOURCE[x][y]); // do this unless you need to do something with pointer
}
}
Then you can make printGrid with either of the following signatures:
void printGrid(const char& grid)
{
// do something usefull
}
or
void printGrid(const char* grid)
{
// do something usefull
}
Extending James's Answer, you may change your code as below as it sees that the it passes pointer to an array of 4 char rather than just array of char.
for(int x = 0; x < 20; x+=4)
{
for(int y = 0; y < 20; y+=4)
{
char const (*p4[4])[4] =
{
(const char(*)[4])(SOURCE[x] + y),
(const char(*)[4])(SOURCE[x + 1] + y),
(const char(*)[4])(SOURCE[x + 2] + y),
(const char(*)[4])(SOURCE[x + 3] + y)
};
}
}

structs within structs, dynamic memory allocation

I am making a 3D application where a boat has to drive through buoy tracks. I also need to store the tracks in groups or "layouts". The buoys class is basically a list of "buoy layouts" inside of which is a list of "buoy tracks", inside of which is a list of buoys.
I checked the local variable watcher and all memory allocations in the constructor appear to work. Later when the calculateCoordinates function is called it enters a for loop. On the first iteration of the for loop the functions pointer is used and works fine, but then on this line
ctMain[j+1][1] = 0;
the function pointers are set to NULL. I am guessing it has something to with the structs not being allocated or addressed correctly. I am not sure what to do from here. Maybe I am not understanding how malloc is working.
Update
I replaced the M3DVector3d main_track with double ** main_track, thinking maybe malloc is not handling the typedefs correctly. But I am getting the same error when trying to access the main_track variable later in calculateCoordinates.
Update
It ended up being memory corruption caused by accessing a pointer wrong in the line
rotatePointD(&(cTrack->main_track[j]), rotation);
It only led to an error later when I tried to access it.
// Buoys.h
////////////////////////////////////////////
struct buoy_layout_t;
struct buoy_track_t;
typedef double M3DVector3d[3];
class Buoys {
public:
Buoys();
struct buoy_layout_t ** buoyLayouts;
int nTrackLayouts;
int currentLayoutID;
void calculateCoordinates();
};
struct buoy_track_t {
int nMain, nYellow, nDistract;
M3DVector3d * main_track,
yellow_buoys,
distraction_buoys;
double (*f)(double x);
double (*fp)(double x);
double thickness;
M3DVector3d start, end;
};
struct buoy_layout_t {
int nTracks;
buoy_track_t ** tracks;
};
// Buoys.cpp
/////////////////////////////
// polynomial and its derivative, for shape of track
double buoyfun1(double x) {return (1.0/292.0)*x*(x-12.0)*(x-24.0);}
double buoyfun1d(double x) {return (1.0/292.0)*((3.0*pow(x,2))-(72.0*x)+288.0);}
// ... rest of buoy shape functions go here ...
Buoys::Buoys() {
struct buoy_layout_t * cLayout;
struct buoy_track_t * cTrack;
nTrackLayouts = 1;
buoyLayouts = (buoy_layout_t **) malloc(nTrackLayouts*sizeof(*buoyLayouts));
for (int i = 0; i < nTrackLayouts; i++) {
buoyLayouts[i] = (buoy_layout_t *) malloc(sizeof(*(buoyLayouts[0])));
}
currentLayoutID = 0;
// ** Layout 1 **
cLayout = buoyLayouts[0];
cLayout->nTracks = 1;
cLayout->tracks = (buoy_track_t **) malloc(sizeof(*(cLayout->tracks)));
for (int i = 0; i < 1; i++) {
cLayout->tracks[i] = (buoy_track_t *) malloc (sizeof(*(cLayout->tracks)));
}
cTrack = cLayout->tracks[0];
cTrack->main_track = (M3DVector3d *) malloc(30*sizeof(*(cTrack->main_track)));
cTrack->nMain = 30;
cTrack->f = buoyfun1;
cTrack->fp = buoyfun1d;
cTrack->thickness = 5.5;
cTrack->start[0] = 0; cTrack->start[1] = 0; cTrack->start[2] = 0;
cTrack->end[0] = 30; cTrack->end[1] = 0; cTrack->end[2] = -19;
// ... initialize rest of layouts here ...
// ** Layout 2 **
// ** Layout 3 **
// ...
// ** Layout N **
calculateCoordinates();
}
void Buoys::calculateCoordinates()
{
int i, j;
buoy_layout_t * cLayout = buoyLayouts[0];
for (i = 0; i < (cLayout->nTracks); i++) {
buoy_track_t * cTrack = cLayout->tracks[i];
M3DVector3d * ctMain = cTrack->main_track;
double thickness = cTrack->thickness;
double rotation = getAngleD(cTrack->start[0], cTrack->start[2],
cTrack->end[0], cTrack->end[2]);
double full_disp = sqrt(pow((cTrack->end[0] - cTrack->start[0]), 2)
+ pow((cTrack->end[2] - cTrack->start[2]), 2));
// nBuoys is nBuoys per side. So one side has nBuoys/2 buoys.
for (j=0; j < cTrack->nMain; j+=2) {
double id = j*((full_disp)/(cTrack->nMain));
double y = (*(cTrack->f))(id);
double yp = (*(cTrack->fp))(id);
double normal, normal_a;
if (yp!=0) {
normal = -1.0/yp;
}
else {
normal = 999999999;
}
if (normal > 0) {
normal_a = atan(normal);
}
else {
normal_a = atan(normal) + PI;
}
ctMain[j][0] = id + ((thickness/2.0)*cos(normal_a));
ctMain[j][1] = 0;
ctMain[j][2] = y + ((thickness/2.0)*sin(normal_a));
ctMain[j+1][0] = id + ((thickness/2.0)*cos(normal_a+PI));
ctMain[j+1][1] = 0; // function pointers get set to null here
ctMain[j+1][2] = y + ((thickness/2.0)*sin(normal_a+PI));
}
for (j=0; j < cTrack->nMain; j++) {
rotatePointD(&(cTrack->main_track[j]), rotation);
}
}
}
Unless there are requirements for learning pointers or you cannot use STL, given you are using C++ I'd strongly recommend you use more STL, it is your friend. But anyways...
First, the type of ctMain is *M3DVector3D. So you can safely access ctMain[0], but you cannot access ctMain[1], maybe you meant for the type of ctMain to be **M3DVector3D, in which case the line for initialization you had written which is:
cTrack->main_track = (M3DVector3d *) malloc(30*sizeof(*(cTrack->main_track)));
would make sense.
More Notes
Why are you allocating 30 of these here?
cTrack->main_track = (M3DVector3d *) malloc(30*sizeof(*(cTrack->main_track)));
Given the type of main_track, you only need:
cTrack->main_track = (M3DVector3d *) malloc(sizeof(M3DVector3d));
In addition, for organizational purposes, when doing sizeof you may want to give the actual type to check the sizeof, as opposed to the variable (there should be no difference, just organizational), these two changes:
buoyLayouts = (buoy_layout_t **) malloc(nTrackLayouts*sizeof(buoy_layout_t*));
for (int i = 0; i < nTrackLayouts; i++) {
buoyLayouts[i] = (buoy_layout_t *) malloc(sizeof(buoy_layout_t));
}
cLayout->tracks = (buoy_track_t **) malloc(clayout->nTracks * sizeof(buoy_track_t*));
for (int i = 0; i < 1; i++) {
cLayout->tracks[i] = (buoy_track_t *) malloc(sizeof(buoy_track_t));
}