I have this struct with an array in it that is supposed to tell the enemy where to walk. The problem is that I get a segmentation fault and I can not figure out why.
The Struct
struct Enemy {
bool scared;
bool runhome;
int posx;
int posy;
int home[][2]; //{x,y}
};
deceleration
struct Enemy pinky = {false, false, 1,1, {{1,1},{1,2},{1,3},{2,3},{3,3},{4,3},{4,2},{4,1},{3,1},{2,1}}};
struct Enemy clyde = {false, false, 1,19, {{1,19},{2,19},{3,19},{4,19},{5,19},{6,19},{7,19},{8,19},{8,18},{8,17},{8,16},{8,15},{7,15},{6,15},{6,16},{6,17},{5,17},{4,17},{3,17},{2,17},{1,17},{1,18}}};
struct Enemy blinky = {false, false, 17,1, {{17,1},{17,2},{17,3},{16,3},{15,3},{14,3},{14,2},{14,1},{15,1},{16,1}}};
struct Enemy inky = {false, false, 17,19, {{17,19},{16,19},{15,19},{14,19},{13,19},{12,19},{11,19},{10,19},{10,18},{10,17},{10,16},{10,15},{11,15},{12,15},{12,16},{12,17},{13,17},{14,17},{15,17},{16,17},{17,17},{17,18}}};
where I call home
else if(ghost->runhome) {
int *targetposition;
//decides which way to move
targetposition = optimalpath(ghost->posx, ghost->posy, ghost->home[0][0], ghost->home[0][1]);
}
before I added the home array I did not get any errors but as soon as it was added I got a segmentation fault error.
CodePudding user response:
You declared a structure with a flexible array member
struct Enemy {
bool scared;
bool runhome;
int posx;
int posy;
int home[][2]; //{x,y}
};
A memory for the flexible array was not yet allocated. So you may not use the array. You need to allocate dynamically memory for the flexible array member together with an object of the structure type.
For example
struct Enemy *pinky = malloc( sizeof( struct Enemy ) sizeof( int[10][2] ) );
Also you need to track how many elements the flexible array member has.
CodePudding user response:
If you really need/want compile time initialisation...
Here you initialise 4 independent arrays of "movements" (I've truncated for brevity.)
int pinkyHome[][2] = { {1,1},{1,2},{1,3},{2,3}, };
int clydeHome[][2] = { {1,19},{2,19},{3,19},{4,19},{5,19}, };
int blinkyHome[][2] = { {17,1},{17,2},{17,3},{16,3},{15,3}, };
int inkyHome[][2] = { {17,19},{16,19}, };
Then define a macro to save lots of redundant typing;
#define MAC( who ) #who, sizeof who##Home / sizeof who##Home[ 0 ], who##Home
Then you can add each (variable length) array of "moves" to the structure (as a pointer), (including how many there are for each).
Because we can, I've adjusted your struct (including typedef) to store the character's name, the number of moves (in this case 'truncated') and the full list of moves...
typedef struct {
bool scared;
bool runhome;
int posx;
int posy;
char *name; // New to squeeze into macro
int nsteps;
int (*home)[2];
} Enemy_t;
Now we can declare the four characters, compile time initialised...
Enemy_t pinky = { false, false, 1, 1, MAC( pinky ) };
Enemy_t clyde = { false, false, 1, 19, MAC( clyde ) };
Enemy_t blinky = { false, false, 17, 1, MAC( blinky ) };
Enemy_t inky = { false, false, 17, 19, MAC( inky ) };
To show how it works:
void show( Enemy_t *p ) {
printf( "%s:\n", p->name );
for( int i = 0; i < p->nsteps; i )
printf( "p->home[%d][0] %d p->home[%d][1] %d\n", i, p->home[i][0], i, p->home[i][1] );
printf( "\n" );
}
int main() {
show( &pinky );
show( &clyde );
show( &blinky );
show( &inky );
return 0;
}
And, finally, the proof of function...
pinky:
p->home[0][0] 1 p->home[0][1] 1
p->home[1][0] 1 p->home[1][1] 2
p->home[2][0] 1 p->home[2][1] 3
p->home[3][0] 2 p->home[3][1] 3
clyde:
p->home[0][0] 1 p->home[0][1] 19
p->home[1][0] 2 p->home[1][1] 19
p->home[2][0] 3 p->home[2][1] 19
p->home[3][0] 4 p->home[3][1] 19
p->home[4][0] 5 p->home[4][1] 19
blinky:
p->home[0][0] 17 p->home[0][1] 1
p->home[1][0] 17 p->home[1][1] 2
p->home[2][0] 17 p->home[2][1] 3
p->home[3][0] 16 p->home[3][1] 3
p->home[4][0] 15 p->home[4][1] 3
inky:
p->home[0][0] 17 p->home[0][1] 19
p->home[1][0] 16 p->home[1][1] 19