Random matrix struct creation - c

I'm trying to make a struct that generates a random matrix and am getting "error: expected â=â, â,â, â;â, âasmâ or â_attribute_â before âmatrixâ" when compiling. How can I get this to work effectively and efficiently?
I guess expected errors usually are caused by typos but I don't see any.
I'm very new to C so pointers and malloc are quite foreign to me. I really appreciate your help.
/* It's called RandomMatrixMaker.c */
#include <stdio.h>
#include <stdlib.h>
typdef struct {
char* name;
int MID;
int MRows;
int MCols;
long[][]* MSpace;
} matrix;
matrix makeRIDMatrix(char* name, int MID, int MRows, int MCols) {
matrix m;
static int i, j, r;
m.name = name;
m.MID = MID;
m.MRows = MRows;
m.MCols = MCols;
for (i=0; i<m.MRows; i++) {
for (j=0; i<m.MCols; j++) {
r = random(101);
*(m.MSpace[i][j]) = r;
}
}
return m;
}
int main(void) {
makeRIDMatrix("test", 1, 10, 10);
return 0;
}

There is indeed a typo. You misspelled typedef:
typdef struct {
should be:
typedef struct {
EDIT:
Also, there's no reason to use static here:
static int i, j, r;
You can just get rid of the static modifier.
int i, j, r;

As another poster mentioned, there's a typo, but even with that corrected, it wouldn't compile, due to the definition of matrix.MSpace.
Let's begin in makeRIDMatrix(). You've declared an automatic (stack) variable of type "matrix". At the end of the function, you return that object. Whilst this is permissible, it's not advisable. If the struct is large, you will be copying a lot of data unnecessarily. Better to pass a pointer to a matrix into makeRIDMatrix(), and have makeRIDMatrix() fill in the contents.
The test in the inner loop is against i, but should be against j.
Next, let's look at the definition of "matrix". The definition of "MSpace" is a mess, and wouldn't even compile. Even if it did, because you haven't defined the length of a row, the compiler would not be able to calcuate the offset to any given item in the array. You want a two-dimensional array without giving the row length, but you can't do that in C. You can in other languages, but not C.
There's a lot more I could point out, but I'd be missing the real point. The real point is this:
C Is Not Java.
(It's also not one of the interpreted languages such as JavaScript, PHP, Python, Ruby and so on.)
You don't get dynamically-expanding arrays; you don't get automatic allocation of memory; you don't get garbage collection of unreferenced memory.
What you need is something more like this:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct {
char* name;
int MID;
unsigned int MRows;
unsigned int MCols;
long *MSpace;
} matrix;
void makeRIDMatrix(matrix *pmx, char* name, int MID,
unsigned int MRows, unsigned int MCols) {
int i, j;
long *MSpace = malloc(sizeof(*MSpace)*MRows*MCols);
if (MSpace == NULL) {
return;
}
pmx->name = name;
pmx->MID = MID;
pmx->MRows = MRows;
pmx->MCols = MCols;
pmx->MSpace = MSpace;
srandom((unsigned int)time(NULL));
for (i=0; i<MRows; i++) {
for (j=0; i<MCols; j++) {
long int r = random() % 101L;
*(MSpace++) = r;
}
}
}
inline long * item_addr(const matrix *pmx,
unsigned int row, unsigned int col) {
if (pmx == NULL || pmx->MSpace == NULL
|| row >= pmx->MRows || col >= pmx->MCols) {
return NULL;
}
return &(pmx->MSpace[row * pmx->MCols + col]);
}
long get_item(const matrix *pmx, unsigned int row, unsigned int col) {
long *addr = item_addr(pmx, row, col);
return addr == NULL ? 0L : *addr;
}
void set_item(matrix *pmx,
unsigned int row, unsigned int col,
long val) {
long *addr = item_addr(pmx, row, col);
if (addr != NULL) {
*addr = val;
}
}
int main(void) {
matrix m;
makeRIDMatrix(&m, "test", 1, 10, 10);
return 0;
}
Note a few things here. Firstly, for efficiency, I fill the array as if it were one-dimensional. All subsequent get/set of array items should be done through the getter/setter functions, for safety.
Secondly, a hidden nasty: makeRIDMatrix() has used malloc() to allocate the memory - but it's going to be job of the calling function (or its successors) explciitly to free() the allocated pointer when it's finished with.
Thirdly, I've changed the rows/cols variables to unsigned int - there's little sense in definining an array with negative indices!
Fourthly: little error checking. For example, makeRIDMatrix() neither knows nor cares whether the parameter values are sensible (e.g. the matrix pointer isn't checked for NULLness). That's an exercise for the student.
Fifthly, I've fixed your random number usage - after a fashion. Another exercise for the student: why is the way I did it not good practice?
However - all of this is moot. You need to get yourself a good C textbook, or a good online course, and work through the examples. The code you've given here shows that you're punching above your weight at the moment, and you need to develop some more C muscles before going into that ring!

In relation to your question about "variable sized arrays", you could have something like:
/* can stick this into your struct, this is just an example */
size_t rows, cols;
long **matrix;
/* set the values of rows, cols */
/* create the "array" of rows (array of pointers to longs) */
matrix = (long**)malloc(rows * sizeof(long*));
/* create the array of columns (array of longs at each row) */
for (i = 0; i < rows; i++)
matrix[i] = (long*)malloc(cols * sizeof(long));
/* ... */
/* free the memory at the end */
for (i = 0; i < rows; i++)
free(matrix[i]);
free(matrix);
Then you can just access the dynamically allocated matrix similar to any other array of arrays.
ie. to set element at the first row (row 0) and fourth column (column 3) to 5:
matrix[0][3] = 5;

Related

How to return an array from function A and then function B takes this array

I have two functions in my main function.
I've tried to accomplish this problem with pointers, but as a beginner, it is very complicated to work with this.
int main(){
int *p;
p = function_A();
function_B(p);
return 0;
}
int function_A(){
static int myArray[3];
myArray[0] = 11;
myArray[1] = 22;
myArray[2] = 33;
return myArray;
}
int function_B(int *myPointer){
// Here I just want to print my array I've got from function_A() to the
// console
printf("%d", *myPointer)
return 0;
}
function_A should return a array and function_B should take this array.
Thanks!
There are some issues your compiler will already have told you.
First, you should define the functions before calling them, or at least forward declare them.
Second, to return an array, you need to return a pointer to the first element of this array, i.e. return type is int * and not int.
Third, as FredK pointed out, when you receive just a pointer, you have no chance to determine how many elements are in the array it points to. You can either terminate the array with a specific value, e.g. 0, or you need to return the size of the array, too.
See the following adaptions made to your program:
int* function_A(int *size){
static int myArray[3];
myArray[0] = 11;
myArray[1] = 22;
myArray[2] = 33;
if (size) {
*size = 3;
}
return myArray;
}
void function_B(int *myPointer, int size){
for (int i=0; i<size; i++) {
printf("%d\n", myPointer[i]);
}
}
int main(){
int *p;
int size=0;
p = function_A(&size);
function_B(p,size);
return 0;
}
Note: a reference to an array degrades to the address of the first byte of the array.
the following proposed code:
cleanly compiles
incorporates the comments to the question
assumes the programmer already knows the size of the array
performs the desired functionality
appended '\n' to format string of calls to printf() so output on separate lines
and now, the proposed code:
#include <stdio.h>
int * function_A( void );
void function_B(int *myPointer);
int main( void )
{
int *p;
p = function_A();
function_B(p);
return 0;
}
int * function_A()
{
static int myArray[3];
myArray[0] = 11;
myArray[1] = 22;
myArray[2] = 33;
return myArray;
}
void function_B(int *myPointer)
{
printf("%d\n", myPointer[0]);
printf("%d\n", myPointer[1]);
printf("%d\n", myPointer[2]);
}
a run of the program produces the following output:
11
22
33
Let's say you have a function that creates an array of ints:
int *create_int_array(const size_t num)
{
int *iarray;
size_t i;
if (num < 1)
return NULL; /* Let's not return an empty array. */
iarray = malloc(num * sizeof iarray[0]);
if (!iarray)
return NULL; /* Out of memory! */
/* Fill in the array with increasing integers. */
for (i = 0; i < num; i++)
iarray[i] = i + 1;
return iarray;
}
Let's say tou have a function that calculates the sum of the integers in the array. If we ignore any overflow issues, it could look like this:
int sum_int_array(const int *iarray, const size_t num)
{
int sum = 0;
size_t i;
/* Sum of an empty array is 0. */
if (num < 1)
return 0;
for (i = 0; i < num; i++)
sum += iarray[i];
return sum;
}
Note that sizeof is not a function, but a C language keyword. Its argument is only examined for its size. Thus, sizeof iarray[0] yields the size of each element in iarray, and is completely safe and valid even if iarray is undefined or NULL at that point. You see that idiom a lot in C programs; learn to read it as "size of first element of iarray", which is the same as "size of each element in iarray", because all C array elements have the exact same size.
In your main(), you could call them thus:
#ifndef NUM
#define NUM 5
#endif
int main(void)
{
int *array, result;
array = create_int_array(NUM);
if (!array) {
fprintf(stderr, "Out of memory!\n");
exit(EXIT_FAILURE);
}
result = sum_int_array(array, NUM);
printf("Sum is %d.\n", result);
free(array);
return EXIT_SUCCESS;
}
As you can see, there is really not much to it. Well, you do need to get familiar with the pointer syntax.
(The rule I like to point out is that when reading pointer types, read the specifiers from right to left, delimited by * read as a pointer to. Thus, int *const a reads as "a is a const, a pointer to int", and const char **b reads as "b is a pointer to a pointer to const char".)
In this kind of situations, a structure describing an array makes much more sense. For example:
typedef struct {
size_t max; /* Maximum number of elements val[] can hold */
size_t num; /* Number of elements in val[] */
int *val;
} iarray;
#define IARRAY_INIT { 0, 0, NULL }
The idea is that you can declare a variable of iarray type just as you would any other variable; but you also initialize those to an empty array using the IARRAY_INIT macro. In other words, thus:
iarray my_array = IARRAY_INIT;
With that initialization, the structure is always initialized to a known state, and we don't need a separate initialization function. We really only need a couple of helper functions:
static inline void iarray_free(iarray *array)
{
if (array) {
free(array->val);
array->max = 0;
array->num = 0;
array->val = NULL;
}
}
/* Try to grow the array dynamically.
Returns the number of elements that can be added right now. */
static inline size_t iarray_need(iarray *array, const size_t more)
{
if (!array)
return 0;
if (array->num + more > array->max) {
size_t max = array->num + more;
void *val;
/* Optional: Growth policy. Instead of allocating exactly
as much memory as needed, we allocate more,
in the hopes that this reduces the number of
realloc() calls, which tend to be a bit slow.
However, we don't want to waste too much
memory by allocating and then not using it. */
if (max < 16) {
/* Always allocate at least 16 elements, */
max = 16;
} else
if (max < 65536) {
/* up to 65535 elements add 50% extra, */
max = (3*max) / 2;
} else {
/* then round up to next multiple of 65536, less 16. */
max = (max | 65535) + 65521;
}
val = realloc(array->val, max * sizeof array->val[0]);
if (!val) {
/* We cannot grow the array. However, the old
array is still intact; realloc() does not
free it if it fails. */
return array->max - array->num;
}
/* Note: the new elements in array->val,
array->val[array->max] to
array->val[max-1], inclusive,
are undefined. That is fine, usually,
but might be important in some special
cases like resizing hash tables or such. */
array->max = max;
array->val = val;
}
return array->max - array->num;
}
/* Optional; same as initializing the variable to IARRAY_INIT. */
static inline void iarray_init(iarray *array)
{
array->max = 0;
array->num = 0;
array->val = NULL;
}
The static inline bit means that the functions are only visible in this compilation unit, and the compiler is free to implement the function directly at the call site. Basically, static inline is used for macro-like functions and accessor functions. If you put the structure in a header file (.h), you'd put the related static inline helper functions in it as well.
The growth policy part is only an example. If you omit the growth policy, and always reallocate to array->num + more elements, your code will call realloc() very often, potentially for every int appended. In most cases, doing it that often will slow down your program, because realloc() (as well as malloc(), calloc()) is kind-of slow. To avoid that, we prefer to pad or round up the allocation a bit: not too much to waste allocated but unused memory, but enough to keep the overall program fast, and not bottlenecked on too many realloc() calls.
A "good growth policy" is very much up to debate, and really depends on the task at hand. The above one should work really well on all current operating systems on desktop machines, laptops, and tablets, when the program needs only one or only a handful of such arrays.
(If a program uses many such arrays, it might implement an iarray_optimize() function, that reallocates the array to exactly the number of elements it has. Whenever an array is unlikely to change size soon, calling that function will ensure not too much memory is sitting unused but allocated in the arrays.)
Let's look at an example function that uses the above. Say, the obvious one: appending an integer to the array:
/* Append an int to the array.
Returns 0 if success, nonzero if an error occurs.
*/
int iarray_append(iarray *array, int value)
{
if (!array)
return -1; /* NULL array specified! */
if (iarray_need(array, 1) < 1)
return -2; /* Not enough memory to grow the array. */
array->val[array->num++] = value;
return 0;
}
Another example function would be one that sorts the ints in an array by ascending or descending value:
static int cmp_int_ascending(const void *ptr1, const void *ptr2)
{
const int val1 = *(const int *)ptr1;
const int val2 = *(const int *)ptr2;
return (val1 < val2) ? -1 :
(val1 > val2) ? +1 : 0;
}
static int cmp_int_descending(const void *ptr1, const void *ptr2)
{
const int val1 = *(const int *)ptr1;
const int val2 = *(const int *)ptr2;
return (val1 < val2) ? +1 :
(val1 > val2) ? -1 : 0;
}
static void iarray_sort(iarray *array, int direction)
{
if (array && array->num > 1) {
if (direction > 0)
qsort(array->val, array->num, sizeof array->val[0],
cmp_int_ascending);
else
if (direction < 0)
qsort(array->val, array->num, sizeof array->val[0],
cmp_int_descending);
}
}
Many new programmers do not realize that the standard C library has that nifty and quite efficient qsort() function for sorting arrays; all it needs is a comparison function. If the direction is positive for iarray_sort(), the array is sorted in ascending order, smallest int first; if direction is negative, then in descending order, largest int first.
A simple example main() that reads in all valid ints from standard input, sorts them, and prints them in ascending order (increasing value):
int main(void)
{
iarray array = IARRAY_INIT;
int value;
size_t i;
while (scanf(" %d", &value) == 1)
if (iarray_append(&array, value)) {
fprintf(stderr, "Out of memory.\n");
exit(EXIT_FAILURE);
}
iarray_sort(&array, +1); /* sort by increasing value */
for (i = 0; i < array.num; i++)
printf("%d\n", array.val[i]);
iarray_free(&array);
return EXIT_SUCCESS;
}
If size of array is indeed 3 (or other small fixed value), then you can simply use structs as values, something like:
struct ints3 {
int values[3];
// if needed, can add other fields
}
int main(){
struct ints3 ints;
ints = function_A();
function_B(&ints);
return 0;
}
// note about function_A signature: void is important,
// because in C empty () means function can take any arguments...
struct ints3 function_A(void) {
// use C designated initialiser syntax to create struct value,
// and return it directly
return (struct ints3){ .values = { 11, 22, 33 } };
}
int function_B(const struct ints3 *ints) {
// pass struct as const pointer to avoid copy,
// though difference to just passing a value in this case is insignificant
// could use for loop, see other answers, but it's just 3 values, so:
printf("%d %d %d\n", ints->values[0], ints->values[1], ints->values[2]);
return 0; // does this function really need return value?
}

How to return int array in C using this Collatz Conjecture function?

I have a function for the Collatz Conjecture that returns an int Array but I keep getting a segmentation fault error and am not sure why.
int n=1;
int* col fuction(int x){
int *totalList;
totalList[0]=x;
while (x != 1){
if (x%2==0){
x=x/2;
}else{
x= 3* x + 1;
}
totalList[n]= x;
n++;
}
totalList[n+1]=1;
return totalList;
}
It is suppose to return the integers in a row with commas in between each number. I call it as shown below:
int *colAns;
colAns= col(num);
for (int k =0; k< n; k++){
printf("%d", colAns[k]);
if(colAns[k] != 1){
printf(",");
}
}
printf("\n");
Your issue lies within the first few lines of col_function().
int* col_fuction(int x){
int *totalList;
totalList[0]=x;
// ...
}
When the int* called totalList gets created on the stack, it takes whatever value was previously there. There's a slim chance that the pointer value will be anything even owned by the process, let alone something valid/usable.
What you need is a dynamically-allocated value that can grow as values are added to it. For this, we use malloc to allocate a pre-determined amount of memory. Because the collatz function is recursive and the number of elements cannot be determined by merely looking at it, we cannot presume to know exactly how much memory it will take, so it should grow as numbers are added to it. For this, we use realloc. What's nice about realloc is that, if the first parameter is NULL, it is guaranteed by the standard to work like malloc.
The only other thing you really need is a couple of size_t values inside of a struct in order to keep track of the current index as well as the allocated space. Something like this should be sufficient:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define CHUNK_SIZE 100
typedef struct dynarray
{
int *values;
size_t allocated, used;
} dynarray;
int dynarray_init(dynarray *d)
{
memset(d, 0, sizeof(dynarray));
return 0;
}
int dynarray_deinit(dynarray *d)
{
free(d->values);
memset(d, 0, sizeof(dynarray));
return 0;
}
int dynarray_append(dynarray *d, int val)
{
int *tmp = NULL;
size_t i;
if(d->used + 1 >= d->allocated)
{
if((tmp = (int*)realloc(d->values, (d->allocated + CHUNK_SIZE)*sizeof(int))) == NULL)
{
perror("realloc() failure");
return 1;
}
else
{
d->values = tmp;
d->allocated += CHUNK_SIZE;
}
}
d->values[d->used++] = val;
}
Use dynarray_append() to add values to the list after it's been initialized.

C string pointer initializes itself then de-initializes itself?

This is an excerpt from a Conway's Game of Life-program that I'm writing. In this part I'm trying to get the program to read a file that specifies what cells are to be populated at the start of the game (i.e. the seed).
I get a weird bug. In the read_line function, the program crashes online[i++] = ch statement. When I debug the program, I see that the line-pointer is NULL when it crashes. Fair enough, I think, I should initialize line. But here is the (for me) strange part:
The read_line function has already successfully execute twice and got me the first two lines (4\n and 3 6\n) from the seed file. And when I look at the execution in the debugger, I see that line is indeed holding a value in those first two executions of read_line. How is this possible? How can line be initialized without me initializing it and then suddenly not be initialized anymore?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define MAX_COORDINATE_SIZE 50
#define MAX_FILENAME_SIZE 20
#define MAX_GENERATIONS 10
#define MAX_REPETITION_PERIOD 4
struct coord{ //Holds coordinates to a cell
int x;
int y;
};
struct cell{
int pop; //Populated
int age;
};
struct coord *read_init(FILE *fp, int *i);
static int read_line(FILE *fp, char *line, int max_length);
struct coord read_coords(char *line);
struct cell **create_board(int x, int y);
struct cell **start_game(FILE *fp, int nrows, int ncols);
struct cell new_cell(int x, int y, int pop, int age);
void print_board(struct cell **board, int nrows, int ncols);
void populate_board(struct coord *coords, struct cell ***board, int *n);
int main(int argc, const char * argv[]) {
int gens;
char gens_string[MAX_GENERATIONS];
if(argc != 3){
fprintf(stderr, "Usage: %s <seed-file> <generations>\n<seed-file> can me up to %d characters long\n", argv[0], MAX_FILENAME_SIZE);
exit(1);
}
FILE *fp = fopen(argv[1], "r");
strncat(gens_string, argv[2], MAX_GENERATIONS);
gens = atoi(gens_string);
int nrows = 10;
int ncols = 10;
struct cell **board= start_game(fp, nrows, ncols);
print_board(board, nrows, ncols);
return 0;
}
struct coord *read_init(FILE *fp, int *n){ //Takes in filename and returns list of coordinates to be populated
char raw_n[100];
struct coord *coords;
char *line;
read_line(fp, raw_n, 100); // get the first line of the file (number of popuated cells)
*n = atoi(raw_n);//make an int out of raw_n
coords = malloc(sizeof(struct coord)*(*n)); //Allocate memory for each coord
for(int i = 0; i<(*n); i++){ // for each line in the file (each populated cell)
read_line(fp, line, MAX_COORDINATE_SIZE);
coords[i] = read_coords(line); //Put coordinates in coords
line = '\0';
}
return coords; // return coordinates
}
static int read_line ( FILE *fp, char *line, int max_length)
{
int i;
char ch;
/* initialize index to string character */
i = 0;
/* read to end of line, filling in characters in string up to its
maximum length, and ignoring the rest, if any */
for(;;)
{
/* read next character */
ch = fgetc(fp);
/* check for end of file error */
if ( ch == EOF )
return -1;
/* check for end of line */
if ( ch == '\n' )
{
/* terminate string and return */
line[i] = '\0';
return 0;
}
/* fill character in string if it is not already full*/
if ( i < max_length )
line[i++] = ch;
}
/* the program should never reach here */
return -1;
}
struct coord read_coords(char *line){ // Returns coordinates read from char *line
struct coord c;
char *x;
char *y;
x = malloc(sizeof(char)*MAX_COORDINATE_SIZE);
y = malloc(sizeof(char)*MAX_COORDINATE_SIZE);
int i = 0;
do{
x[i] = line[i]; //Get the x coordinate
i++;
}while(line[i] != ' ');
i++;
do{
y[i-2] = line[i];
i++;
}while(line[i] != '\0');
c.x = atoi(x)-1;
c.y = atoi(y)-1;
return c;
}
void init_board(int nrows, int ncols, struct cell ***board){
*board = malloc(nrows * sizeof(*board) + nrows * ncols * sizeof(**board));
//Now set the address of each row or whatever stackoverflow says
struct cell * const firstrow = *board + nrows;
for(int i = 0; i < nrows; i++)
{
(*board)[i] = firstrow + i * ncols;
}
for(int i = 0; i < nrows; i++){ //fill the entire board with pieces
for(int j = 0; j < ncols; j++){
(*board)[i][j] = new_cell(i, j, 0, 0);
}
}
}
void print_board(struct cell **board, int nrows, int ncols){
printf("--------------------\n");
for(int i = 0; i<nrows; i++){
for(int j = 0; j<ncols; j++){
if(board[i][j].pop == 1){
printf("%d ", board[i][j].age);
}else if(board[i][j].pop == 0){
printf(" ");
}else{
printf("\n\nERROR!");
exit(0);
}
}
printf("\n");
}
printf("--------------------");
printf("\n");
}
struct cell **start_game(FILE *fp, int nrows, int ncols){ //x,y are no of rows/columns, fn is filename
int n; // n is the number of populated cells specified in the seed
struct coord *coords = read_init(fp, &n); // get the list of coords to populate board with
struct cell **board;
init_board(nrows, ncols, &board); // Set up the board
populate_board(coords, &board, &n); //populate the cells specified in the seed
return board;
}
void populate_board(struct coord *coords, struct cell ***board, int *n){
for(int i = 0; i < *n; i++){
(*board)[coords[i].x][coords[i].y].pop = 1; //populate the cell
}
}
struct cell new_cell(int x, int y, int pop, int age){ //Return new populated or non-populated cell with specified coordinates
struct cell c;
c.pop = pop;
c.age = age;
return c;
}
The seed file:
4
3 6
4 6
5 6
5 7
EDIT:
The error message: Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
I shall add that if I add a line line = malloc(sizeof(char)*MAX_COORDINATE_SIZE+1) after the declaration of line in read_init, I still get the same error.
In read_init() :
struct coord *read_init(FILE *fp, int *n){
//...
char *line;
//...
for(int i = 0; i<(*n); i++) {
read_line(fp, line, MAX_COORDINATE_SIZE);
coords[i] = read_coords(line); //Put coordinates in coords
line = '\0'; // <<--- you set line to NULL here.
*line = 0; // this is what you wanted to do, is not necessary...
}
// ....
}
I get a weird bug.
I suggest asking some questions about the compiler output. We should never blindly ignore warnings, after all. Speaking of reading things, I think you're spending too long reading StackOverflow and not long enough reading K&R2e and doing the exercises. We'll come back to that.
In the read_line function, the program crashes on line[i++] = ch statement ... But here is the (for me) strange part: ... The read_line function has already successfully execute twice and got me the first two lines (4\n and 3 6\n) from the seed file
The C and C++ standards rationalise the concept of "undefined behaviour" for this class of errors that are computationally difficult to diagnose. In other words, because you made an error, the behaviour of your program is undefined. It isn't required that your malfunctioning code crash every time, as that would be defining the undefined; instead they leave this "undefined" and the first two times your erroneously code works (whatever that means), purely by coincidence that the uninitialised variable points somewhere accessible. Later on you assign line = '\0';, which changes line to be a null pointer, and then you try to assign into whatever that null pointer points at. That's more undefined behaviour.
How is this possible? How can line be initialized without me initializing it and then suddenly not be initialized anymore?
line isn't initialised; you're using it uninitialised, which happens to coincidentally work (but needs fixing), then you assign it to be a null pointer and dereference a null pointer (more UB that needs fixing). Such is the nature of undefined behaviour. Such is the nature of learning C by guessing. You need a book!
I shall add that if I add a line line = malloc(sizeof(char)*MAX_COORDINATE_SIZE+1) after the declaration of line in read_init, I still get the same error.
You need to fix all of the errors, not just the one. For assistance you could see the warnings/errors your compiler emits. I see more uninitialised access here:
char gens_string[MAX_GENERATIONS]; // <--- where's the initialisation??
// Snip
strncat(gens_string, argv[2], MAX_GENERATIONS); // Boom
There's some really sus code around this comment: //Now set the address of each row or whatever stackoverflow says ... and on that note I want to point out that there are some subtly toxic know-it-alls who answer questions despite having as many misunderstandings as you, a humble person, and so you shouldn't hope to get the same quality of education from StackOverflow as you would from K&R2e... but apparently I'd be toxic for pointing out the egomaniacs and suggesting decent resources to learn from, so that's none of my business 🙄🤷‍♂️ let's just let the sociopaths sabotage the education of everyone huh?
(*board)[i] = firstrow + i * ncols;
Look, there is no guarantee that this even compiles let alone that the address on the right has a suitable alignment to store the type of value on the left. Misaligned access causes more undefined behaviour, which may also work coincidentally rather than logically. Just as you've never seen alignment violations before, so too has the person who suggested you use this code. Assuming the alignment requirements for your implementation are satisfied by this code, we then have the same questions to raise here:
(*board)[i][j] = new_cell(i, j, 0, 0);
Your whole program needs remodelling around the declaration of board changing from struct cell **board to struct cell (*board)[ncols];, for example. It'll become much simpler, and a whole class of bugs related to alignment requirements will disappear. To see the extent of the simplification, here's what your init_board ought to look like:
void init_board(int nrows, int ncols, struct cell (**board)[ncols]){
*board = malloc(nrows * sizeof(*board));
// NOTE: I snipped the erroneous StackOverflow logic around the comment mentioned above; you don't need that crud because of the more suitable choice of type
for(int i = 0; i < nrows; i++){ //fill the entire board with pieces
for(int j = 0; j < ncols; j++){
(*board)[i][j] = (struct cell){ 0, 0 };
}
}
}

2d array in C with negative indices

I am writing a C-program where I need 2D-arrays (dynamically allocated) with negative indices or where the index does not start at zero. So for an array[i][j] the row-index i should take values from e.g. 1 to 3 and the column-index j should take values from e.g. -1 to 9.
For this purpose I created the following program, here the variable columns_start is set to zero, so just the row-index is shifted and this works really fine.
But when I assign other values than zero to the variable columns_start, I get the message (from valgrind) that the command "free(array[i]);" is invalid.
So my questions are:
Why it is invalid to free the memory that I allocated just before?
How do I have to modify my program to shift the column-index?
Thank you for your help.
#include <stdio.h>
#include <stdlib.h>
main()
{
int **array, **array2;
int rows_end, rows_start, columns_end, columns_start, i, j;
rows_start = 1;
rows_end = 3;
columns_start = 0;
columns_end = 9;
array = malloc((rows_end-rows_start+1) * sizeof(int *));
for(i = 0; i <= (rows_end-rows_start); i++) {
array[i] = malloc((columns_end-columns_start+1) * sizeof(int));
}
array2 = array-rows_start; //shifting row-index
for(i = rows_start; i <= rows_end; i++) {
array2[i] = array[i-rows_start]-columns_start; //shifting column-index
}
for(i = rows_start; i <= rows_end; i++) {
for(j = columns_start; j <= columns_end; j++) {
array2[i][j] = i+j; //writing stuff into array
printf("%i %i %d\n",i, j, array2[i][j]);
}
}
for(i = 0; i <= (rows_end-rows_start); i++) {
free(array[i]);
}
free(array);
}
When you shift column indexes, you assign new values to original array of columns: in
array2[i] = array[i-rows_start]-columns_start;
array2[i] and array[i=rows_start] are the same memory cell as array2 is initialized with array-rows_start.
So deallocation of memory requires reverse shift. Try the following:
free(array[i] + columns_start);
IMHO, such modification of array indexes gives no benefit, while complicating program logic and leading to errors. Try to modify indexes on the fly in single loop.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int a[] = { -1, 41, 42, 43 };
int *b;//you will always read the data via this pointer
b = &a[1];// 1 is becoming the "zero pivot"
printf("zero: %d\n", b[0]);
printf("-1: %d\n", b[-1]);
return EXIT_SUCCESS;
}
If you don't need just a contiguous block, then you may be better off with hash tables instead.
As far as I can see, your free and malloc looks good. But your shifting doesn't make sense. Why don't you just add an offset in your array instead of using array2:
int maxNegValue = 10;
int myNegValue = -6;
array[x][myNegValue+maxNegValue] = ...;
this way, you're always in the positive range.
For malloc: you acquire (maxNegValue + maxPosValue) * sizeof(...)
Ok I understand now, that you need free(array.. + offset); even using your shifting stuff.. that's probably not what you want. If you don't need a very fast implementation I'd suggest to use a struct containing the offset and an array. Then create a function having this struct and x/y as arguments to allow access to the array.
I don't know why valgrind would complain about that free statement, but there seems to be a lot of pointer juggling going on so it doesn't surprise me that you get this problem in the first place. For instance, one thing which caught my eye is:
array2 = array-rows_start;
This will make array2[0] dereference memory which you didn't allocate. I fear it's just a matter of time until you get the offset calcuations wrong and run into this problem.
One one comment you wrote
but im my program I need a lot of these arrays with all different beginning indices, so I hope to find a more elegant solution instead of defining two offsets for every array.
I think I'd hide all this in a matrix helper struct (+ functions) so that you don't have to clutter your code with all the offsets. Consider this in some matrix.h header:
struct matrix; /* opaque type */
/* Allocates a matrix with the given dimensions, sample invocation might be:
*
* struct matrix *m;
* matrix_alloc( &m, -2, 14, -9, 33 );
*/
void matrix_alloc( struct matrix **m, int minRow, int maxRow, int minCol, int maxCol );
/* Releases resources allocated by the given matrix, e.g.:
*
* struct matrix *m;
* ...
* matrix_free( m );
*/
void matrix_free( struct matrix *m );
/* Get/Set the value of some elment in the matrix; takes logicaly (potentially negative)
* coordinates and translates them to zero-based coordinates internally, e.g.:
*
* struct matrix *m;
* ...
* int val = matrix_get( m, 9, -7 );
*/
int matrix_get( struct matrix *m, int row, int col );
void matrix_set( struct matrix *m, int row, int col, int val );
And here's how an implementation might look like (this would be matrix.c):
struct matrix {
int minRow, maxRow, minCol, maxCol;
int **elem;
};
void matrix_alloc( struct matrix **m, int minCol, int maxCol, int minRow, int maxRow ) {
int numRows = maxRow - minRow;
int numCols = maxCol - minCol;
*m = malloc( sizeof( struct matrix ) );
*elem = malloc( numRows * sizeof( *elem ) );
for ( int i = 0; i < numRows; ++i )
*elem = malloc( numCols * sizeof( int ) );
/* setting other fields of the matrix omitted for brevity */
}
void matrix_free( struct matrix *m ) {
/* omitted for brevity */
}
int matrix_get( struct matrix *m, int col, int row ) {
return m->elem[row - m->minRow][col - m->minCol];
}
void matrix_set( struct matrix *m, int col, int row, int val ) {
m->elem[row - m->minRow][col - m->minCol] = val;
}
This way you only need to get this stuff right once, in a central place. The rest of your program doesn't have to deal with raw arrays but rather the struct matrix type.

Declaring a 2-dimensional array of unknown size, C

I have an array declared as a member of a struct in C. The array is declared as:
char mValue[MAXROWS][MAXCOLUMNS];
where MAXROWS and MAXROWS are 300. Is there a better way to do this? I mean, should I declare these as pointers instead?
Thanks!
As the previous poster suggested, a good way is to create a linear array and then "convert it to 2D". Many times, caching the 2D pointers greatly increases the speed of programs that use this array, like so:
mystruct *p = (mystruct*)calloc(ROWS * COLUMNS, sizeof(mystruct));
mystruct **p2 = (mystruct**)calloc(ROWS, sizeof(mystruct*));
for (int i = 0; i < ROWS; i++)
p2[i] = p + i*COLUMNS;
Then, you can simply access a 2D element with:
p2[row][column] = foo;
If all your rows are the same size, you should use a 1D array with the rows stored in sequence:
ABCDE
FGHIJ ---> ABCDEFGHIJKLMNO
KLMNO
The element at row i, column j will be at index i * ROW_LENGTH + j in the 1D array.
You can allocate the array using malloc(ROW_LENGTH * NUM_ROWS).
Another technique is to create a linear array and then convert it to 2d:
char *p = malloc(ROWS * COLUMNS);
// To access x, y
// This is in row-major ordr
*(p + (x * COLUMNS) + y);
I find that, for this kind of code, its better to create helper functions for accessing the elements. Depending on your profiling data, it may make sense to turn these into macros, but be extra careful.
#include <stdio.h> /* For printf */
/* This is the bit that would go in a header, like char2darray.h */
#include <stdlib.h> /* For calloc */
#include <assert.h> /* For assert */
struct Char2DArray
{
int rows;
int columns;
char *values;
};
/* This is the bit that would go in a source file, like char2darray.c */
void C2DA_initialize(struct Char2DArray *array, int rows, int columns)
{
assert(array != 0);
array->values = calloc(rows * columns, sizeof(char));
array->rows = rows;
array->columns = columns;
}
void C2DA_set(struct Char2DArray *array, int row, int column, int value)
{
assert(array != 0);
assert(array->values != 0);
assert(row < array->rows);
assert(row >= 0);
assert(column < array->columns);
assert(column >= 0);
array->values[(row * array->rows) + column] = value;
}
char C2DA_get(struct Char2DArray *array, int row, int column)
{
assert(array != 0);
assert(array->values != 0);
assert(row < array->rows);
assert(row >= 0);
assert(column < array->columns);
assert(column >= 0);
return array->values[(row * array->rows) + column];
}
void C2DA_free(struct Char2DArray *array)
{
free(array->values);
array->values = 0;
}
/* Here's a main.c to use it */
int main()
{
struct Char2DArray a;
C2DA_initialize(&a, 16, 16);
unsigned char c = 0;
int x, y;
for (x=0; x<16; x++) {
for (y=0; y<16; y++) {
C2DA_set(&a, x, y, (char)c);
c++;
}
}
printf("Character with hex value 0x55 is %c\n", C2DA_get(&a, 5, 5));
C2DA_free(&a);
return 0;
}
If the array needs to have a dynamic size, then you either need to make it a pointer or make the array the last member of the struct and play games when allocating the structure size.
Relevant comp.lang.c FAQ entries:
I came across some code that declared a structure like this...
How can I dynamically allocate a multidimensional array?
I found that changing my approach was very useful when faced with a similar problem.
A vector of vectors filled the same task, avoided memory allocation obstacles, and kept the same familiar shorthand. There may be other pitfalls, but I have not encountered them yet.
//Declaration of mValues, undefined size:
std::vector< std::vector<char> > mValues;
//Filling of mValues:
int max_x = 100 ;
int max_y = 100 ;
char char_foo = 'a';
for ( int x = 0; x <= max_x; ++x ) {
vector<char> temp;
for ( int y = 0; y <= max_y; ++y ) {
temp.push_back( char_foo );
}
mValues.push_back( temp );
}
// Referencing with familiar index notation:
mValues[a][b]; //The a-th row's b-th element
If you are struggling with arrays, but strongly desire the familiar indexing language, I have found this to be a good alternative.
Note that indexing order A then B is going to be critical for memory usage when recalling this data. Failure to call the information in an A,B order will be deeply problematic if performance is an issue.

Resources