Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
My name is Bob and I am a three-star programmer. Well, more accurately, I'm trying not to be. I have read a lot on the internet and this site about how "three-star programmer" is a Very Bad Thing. And I can see why. I have read very little (very little that's comprehensible, anyway) about how to avoid it. I mean, there are data sets out there that simply need three or more indices to access their values in a sane manner. So how do I deal with such a set?
I remember seeing a C macro a while back that allows you to store such a data set in a 1D array, and then access the data with three indices, something to the effect of a(i,j,k) is expanded to a[i*NZ*NY + j*NZ +k] but I can't remember how to write it and can't find it on the internet. Anyone know, or have a better idea?
My C is very poor, but wouldn't this simply be:
struct intArray3d {
int NX;
int NY;
int NZ;
int data[]; //or maybe it's data[0]?
};
intArray3d* newIntArray3d(int NX, int NY, int NZ) {
int dataBytes = NX*NY*NZ*sizeof(int);
intArray3d* array = malloc(sizeof(intArray3d) + dataBytes);
array->NX = NX;
array->NY = NY;
array->NZ = NZ;
memset(array->data, 0, dataBytes);
return array;
}
int intArray3dGet(intArray3d* array, int x, int y, int z) {
assert(x<array->NX);
assert(y<array->NY);
assert(z<array->NZ);
return array->data[x*NY*NZ+y*NZ+z];
}
void intArray3dSet(intArray3d* array, int x, int y, int z, int value) {
assert(x<array->NX);
assert(y<array->NY);
assert(z<array->NZ);
array->data[x*NY*NZ+y*NZ+z] = value;
}
Notably:
This avoids unnecessary allocations. The metadata and all of the data happens in a single allocation.
It's super easy to allocate and free.
This tracks the various dimensions alongside the data.
Nobody is going to see a int*** and wonder how big each dimension is. The data already knows.
It's very easy to use correctly.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
[EDIT] The main problem was that the fitness of my evolution returned the same value every time after changing some int into float values. The misterious point is that i restarted the computer and it surprisingly worked again.
I'm calling a function from my main, when i debug the code, the variables contain data, but in the header of the function, when i debug, my data is lost and the reference on memory is the same (i'm compiling with visual Studio 2013), this only happens in some of the variables (you can check which ones in the pictures below)
int main(){
float resultados[NUMCROMOSOMAS][CANTIDADMEDICIONES];
int in[CANTIDADMEDICIONES][NUMVAR];
char gramaticas[NUMCROMOSOMAS][LONGITUDCADENA];
int mejorValorIndividuo[100];
char variableNames[NUMVAR + 1];
float fitness[NUMCROMOSOMAS];
char mejorindividuo[LONGITUDCADENA];
float medicionesObtenidas[NUMCROMOSOMAS][CANTIDADMEDICIONES];
int i,j;
(Initializations, some of the relevant ones are)
for (i = 0; i < NUMCROMOSOMAS; i++)
fitness[i] = 0.0;
for (i = 0; i < CANTIDADMEDICIONES; i++)
in[i][0] = i;
Yeah, that was a bidimensional array using one column
And here is the main loop of my program
int curr = MAXINT;
i = 0;
while ( isNotGoodEnough(curr) ){
i++;
curr = generacion(poblacion, results, input, collectedData, gramaticas, mejorindividuo, variableNames, fitness);
}
return poblacion[0][0];
}
The header of my function is this:
int generacion(int poblacion[NUMCROMOSOMAS][SIZECROMOSOMAS],
float resultados[NUMCROMOSOMAS][CANTIDADMEDICIONES],
int in[CANTIDADMEDICIONES][NUMVAR],
float valoresEsperados[NUMCROMOSOMAS][CANTIDADMEDICIONES],
char gramaticas[NUMCROMOSOMAS][LONGITUDCADENA],
char * mejorIndividuo,
char variableNames[NUMVAR],
float fitness[NUMCROMOSOMAS]){
Here is the compiler before the calling
Here is the compiler right after the calling
What i'm doing wrong?
When you have an argument declaration like
int in[CANTIDADMEDICIONES][NUMVAR]
that's not really what the compiler uses, what it translates it to is
int (*in)[NUMVAR]
In other words in is a pointer and not an array.
What you're seeing in the debugger in the function is the pointer, but since the size of the data pointed to by the pointer is unknown the debugger can't show you the data directly. If you explicitly, in the debugger when in the function, check in[0] you will see that the data is correct.
In other words, it's not a problem with the code, it's how the debugger displays (or rather doesn't display) the data.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I can't figure out how to access a certain parameter inside the structs that I am forced to use. The function gets a hotel and a passport number of one of the guests, and returns the number of the room in which the guest is staying, or NOT_FOUND if the guest is not at the hotel.
struct Guest
{
char name[20];
int passportNumber;
};
struct Room
{
int roomNumber;
int numOfGuests;
struct Guest* allGuests;//the Guests staying in the room
};
struct Hotel
{
int maxRooms;
int numOfUsedRooms;
struct Room** allRooms;
//array of Room* with physical size 'maxRooms'.
//only the first 'numOfUsedRooms' (logical size)
//rooms points to a room,all other pointers are
//NULL
};
int findGuestByPassportNumber(struct Hotel,int);
int main()
{
int i=0,j;
struct Hotel Cucamber;
printf ("before\n");//check
Cucamber.allRooms[i,i]->allGuests[i].name={"Spongebob"};
printf ("after\n");//check
Cucamber.allRooms[i,i]->allGuests[i].passportNumber=1234567890;
printf("%s",Cucamber.allRooms[i]->allGuests[i].name);
return 0;
}
The program doesn't even run because code blocks says:expected expression before '{' token.
First of all, you should google things like "c pointer" and so on and look at some basic tutorials.
Second, please think about your problem a bit first. You want to do a search. So if you search, you don't just know where it is, else you wouldn't have to search in the first place. So this means you'll have to check every available guest, wether his passport number matches the one your looking for.
This is obviously a case for "brute force"-search; so you'll have to do some loops. (Pseudocode):
Int Desiredpassportnumber = 1837748
Char *Name = NULL;
for( int i = 0; i < YourHotel.numberofRooms; i++){
for(int j = 0; j < YourHotel.allRooms[i].numofGuests; j++){
if(YourHotel.allRooms[i].allGuests[j].passportnum == desiredpassportnumber){
Name = YourHotel.allRooms[i].allGuests[j].name
break
}
}
}
If(name== NULL){
//handle No match found
}
Else {
//handle match found
}
This pseudocode, you'll have to add some semicolons and lowercaps some stuff etc. But this should be the idea behind it I think.
Hope this helps you in understanding your problem. :-)
To understand pointers better you should really just google a bit.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
struct atom {
int x;
int y;
int z;
double mass;
};
struct molecule {
struct atom *member;
int natoms;
};
struct system {
struct molecule *fragment;
int nfrags
};
struct system sys;
sys.nfrags=get_number_of_fragments;
????
The system has some number of molecules, each of which has some number of atoms. I don't know how to allocate these things. If I allocate sys.fragment first, it seems like the sizeof(molecule) is undefined since I haven't yet defined the number of atoms (so how can it have a size?). If I try to define the number of atoms first, how do I specify which fragment I'm mallocing for?
I have functions that will return the number of atoms for any molecule/fragment as well as the number of fragments, but am stuck on where to go from here.
AFAIK sizeof(X) cannot be "undefined". In this example, sizeof(molecule) is well defined as the amount of memory it takes to store one molecule instance: One atom Pointer (Note: not the size of any array that you may put here, just the size of the pointer) and one int. So it is perfectly fine to do it the first way and allocate your sys.fragment first:
sys.fragment = malloc(sys.nfrag * sizeof(sys.fragment));
sys.fragment = calloc(sys.nfrag, sizeof sys.fragmemt[0]);
or
sys.fragment = malloc(sys.nfrag * sizeof sys.fragment[0]);
when performance matters (but do not forget the check for overflow!).
malloc(sizeof(system)) Easy as that
You basically have a:
size = X;
first = malloc(X * sizeof(First));
first->second = malloc( N * sizeof(Second));
and so on
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have a code: array of structures that must be sorted. Program works, but:
I can't understand, if Mat is pointer, why not void sort(tArt *sMat), but void sort(tArt sMat[]). I'm really puzzled.
typedef struct{
char data[26];
}tArt;
...
int main(void)
{
FILE* fMat; fMat=fopen..........
tArt* Mat;
...
Mat=malloc(sizeof(tArt));
for(i=0;i<N;i++) fread(&Mat[i],sizeof(tArt),1,fMat);
fclose(fMat);
sort(Mat,N);
...
}
void sort(tArt sMat, int num) {...........}
My guess since we can not see the entire code, is that when you use malloc to dynamically allocate the array you forget to allocate the array for N 'objects'. In other words, I suspect your problem lies in the line
Mat = malloc(sizeof(tArt));
where it should be
Mat = malloc(sizeof(tArt) * N);
On the other hand, when you create explicitly your array with a declaration of the form
tArt Mat[N];
where N is defined somewhere earlier in the ellipses, everything is working as expected.
Hope this helps.
There is no difference between tArt *sMat and tArt sMat[] and tArt sMat[1234], the compiler treat them all as tArt *sMat and ignore the length information.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
So, I'm a C# guy trying my hand at learning C. As a first (personal) project I am attempting to write a basic coordinate geometry library.
Question: Is it again best C programming practices to allocate memory on the heap behind the scenes instead of letting the programmer who is targeting the library do it?
For example, my 'point' struct & related methods:
point.h
/* A basic point type. */
typedef struct point
{
float x;
float y;
float z;
char *note;
}point;
/* Initializes a basic point type. [Free with free_point method] */
point *create_point(float pos_x, float pos_y, float pos_z, char *_note);
/* Frees a point type. */
void free_point(point *_point);
/* Finds the midpoint between two points. */
point *midpoint(point *pt1, point *pt2);
point.c
#include "point.h"
/* Initializes a basic point type. [Free with free_point method] */
point *create_point(float pos_x, float pos_y, float pos_z, char *_note)
{
point *p;
size_t notelen = strlen(_note);
p = (point*)malloc(sizeof(point));
p->x = pos_x;
p->y = pos_y;
p->z = pos_z;
p->note = (char*)calloc(notelen + 1, sizeof(char));
strcpy_s(p->note, notelen + 1, _note);
return p;
}
/* Frees a point type. */
void free_point(point *_point)
{
free (_point->note);
free (_point);
}
/* Creates a midpoint between two points. */
point *midpoint(point *pt1, point *pt2)
{
float mid_x = (pt1->x + pt2->x) * 0.5f;
float mid_y = (pt1->y + pt2->y) * 0.5f;
float mid_z = (pt1->z + pt2->z) * 0.5f;
point *p = create_point(mid_x, mid_y, mid_z, "Midpoint");
return p;
}
Notice that I creating the struct 'point' on the heap FOR whoever implements/uses my lib (in all honesty, this project is just for me and for learning, nevertheless...) via the create_point() method. Is this poor practice? It feels like I am forcing the user into programming a certain way. Same goes with the midpoint() method. Again, you must use pointers to a 'point' struct.
I was unable to find exact questions regarding C library design on SO, but please point me in the right direction if applicable.
Thanks.
It's preference, really. I usually subscribe to letting the user allocate the memory for the object however they wish, and then initializing the members for them.
/* here a non-zero return value might indicate if for example
* we failed to allocate memory for note */
int point_init(struct point* p, int x, int y, char* note)
{
/* ... */
}
/* usage: */
struct point p;
if (point_init(&p, 1, 2, "hello")) {
/* error */
}
This gives the user the option to do things like allocate an array of points that are adjacent in memory, instead of keeping track of an array of pointers to points:
struct point mypoints[NUM_POINTS];
for(size_t i = 0; i < NUM_POINTS; ++i) {
point_init(&mypoints[i], ...);
}
EDIT:
If you want to use the Opaque Pointer strategy to hide the members of your structure from the library user, you will need to allocate the memory for them using the method you described. That's certainly a huge benefit for allocating the structure in your library.
Best practice is to code the library in such a way that the programmer can do what's fastest, since that is a forte of C. For example, the programmer might know that tens of thousands of these point structs will be needed and for the sake of keeping future accesses local might prefer to allocate all the structs in one block of memory. If your library lets the programmer pass pointers in for structs to be initialized, then he can do this. But if you insist on allocating the memory for him, he can't.