I want to reshape an array of length L to one of MxN, however rather than create new memory by copying the elements over in for loops I'd like to do some pointer casting to allow me to access the array with double subscripting (array[X][Y]) .
I've googled around for ages and couldn't find anything helpful.
Any help would really be appreciated.
EDIT: The array of interest is on the heap not stack.
Pointer casting doesn't seem like a good idea here. But if the number of columns is known before run-time, one option I often encounter is to simply define a macro e.g.
#define arrayName(i,j) arrayName[((i)*N) + (j)]
Or
#define ELEMENT(arrayName, i,j) (arrayName)[((i)*N) + (j)]
if you want it to be more flexible.
unions are your friends:
#include <stdio.h>
#define M 5
#define N 4
typedef union {
int a1[M * N];
int a2[M][N];
} U;
int main()
{
U u;
int i, j;
for (i = 0; i < M * N; ++i)
{
u.a1[i] = i;
}
for (i = 0; i < M; ++i)
{
for (j = 0; j < N; ++j)
{
printf("%8d", u.a2[i][j]);
}
printf("\n");
}
return 0;
}
typedefs are your friends:
#include <stdio.h>
#include <stdlib.h>
#define M 5
#define N 4
typedef int Array1D[M * N];
typedef int Array2D[M][N];
int main()
{
Array1D *a1 = malloc(sizeof(*a1));
Array2D *a2 = (Array2D *)a1;
int i, j;
for (i = 0; i < M * N; ++i)
{
(*a1)[i] = i;
}
for (i = 0; i < M; ++i)
{
for (j = 0; j < N; ++j)
{
printf("%8d", (*a2)[i][j]);
}
printf("\n");
}
free(a1);
return 0;
}
Note: above code has now been updated to use heap allocation so as not to break strict aliasing rules.
By the way if you want it super dynamic (as in no sizes are known at compile-time) you can do this by not copying all the values but by creating an index for the 2nd dimension like so:
#include <stdio.h>
#include <stdlib.h>
const int FULL = 100;
const int X = 10;
const int Y = 10;
int *dim1;
int **nested;
int main(void) {
dim1 = malloc(sizeof(int)*FULL);
nested = malloc(sizeof(int*)*X);
for(int i=0; i<X;i++)
{
nested[i] = &dim1[Y*i];
}
dim1[15] = 42;
printf("nested[1][5]: %d",nested[1][5]);
free(nested);
free(dim1);
return 0;
}
Related
I am trying to make a program that first creates an array in another function, returns it and then calls another function that shuffles the contents of the array and returns it. However I am struggling to do this in C since I do not quite understand the array pointer system that has to be used here.
So far my code doesnt return the values 1-20 from makeArray() but instead returns an array full of 0s and I have a feeling it has to do with the c's array pointer system.
Any help would greatly be appreciated! Thank you in advance
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int arrShuffle();
int arrShuffle(int * arr) {
int arr[21];
// shuffle array
for(int j=0; j<20; j++) {
int randInd = (rand() % 20) + 1;
int temp = arr[j];
arr[j] = arr[randInd];
arr[randInd] = temp;
}
return arr;
}
int makeArray() {
int arr[21];
// make array of 1-20
for(int i=0; i < 20; i++) {
arr[i] = i + 1;
}
return arr;
}
void main() {
int *orgArr;
int *modArr;
srand(time(NULL));
orgArr = makeArray();
for(int i=0; i < 20; i++) {
printf("OrgArr: %d\n", orgArr);
}
modArr = arrShuffle(orgArr);
}
You cannot use variables with automatic storage (aka local ones). You must allocate the array so the memory remains valid after the function ends:
int* makeArray() {
int *arr = calloc(21, sizeof *a);
// make array of 1-20
for(int i=0; i < 20; i++) {
arr[i] = i + 1;
}
return arr;
}
Remember to release the array when it is no longer used:
int main() {
int *orgArr;
...
orgArr = makeArray();
...
free(orgArr);
}
As tstanisl pointed out in their answer, a possible solution is to use dynamic memory allocation. My answer, instead, will give you yet another solution: using an array passed by the caller.
NOTE: both solutions are valid and their usefulness depends on the specific needs of your program. There's no "right" universal solution.
void makeArray(int arr[], size_t len) {
for (size_t i = 0; i < len; i += 1) {
arr[i] = (int) (i + 1);
}
}
void cloneAndModifyArray(const int orig[], int new[], size_t len) {
for (size_t i = 0; i < len; i += 1) {
new[i] = orig[i] * 2; // or some other modification
}
}
And you use it like this:
#define ARR_LEN (100)
int main(void) {
int arr[ARR_LEN];
makeArray(arr, ARR_LEN);
int modified_arr[ARR_LEN];
cloneAndModifyArray(arr, modified_arr, ARR_LEN);
return 0;
}
This code should make a sum of the numbers in the main diagonal of a matrix.
#include <stdio.h>
#define RIG 2
#define COL 5
void sum(unsigned int a[RIG][COL]);
int main(){
unsigned int a[RIG][COL] = {{1,2,3,4,5},{6,7,8,9,10}};
sum(a);
}
void sum(unsigned int a[RIG][COL]){
unsigned int c = 0;
unsigned int j = 0;
if (RIG<=COL){
int n = RIG;
}
else{
int n = COL;
}
for (size_t i=0;i<=n-1;++i){
c += a[i][j];
j += 1;
}
printf("%d\n", c);
}
Output:
matrix_sum.c:28:21: error: use of undeclared identifier 'n'
for (size_t i=0;i<=n-1;++i){
^
1 error generated.
I don't get why I can't use the n variable inside the for loop. How can I do that?
This
if (RIG<=COL){
int n = RIG;
}
else{
int n = COL;
}
does not scope n the way you might think it does. Scoping rules are better explained here, but in short: n exists only within each branch of the if/else block. As such, when you attempt to access n in your for-loop later on, it no longer exists!
This is trivially remedied by bringing n into scope, e.g.
int n = COL;
if (RIG <= COL) {
n = RIG;
}
for (size_t i = 0; i <= n - 1; ++i) {
c += a[i][j];
j += 1;
}
I'm writing a C for which I need to create a 2D array. I've found a solution to my problem using double pointers (pointers to pointers) in the following way:
#include <stdio.h>
#include <stdlib.h>
int d = 3;
#define DIM_MAX 9
void changeArray(int d, int *array[d]);
int main()
{
//alocate array of 'd' colummns and 'd' row using malloc using array of pointers
int **array = malloc(d*sizeof(int *));
for(int count = 0; count < d; count++)
{
array[count] = malloc(d*sizeof(int *));
}
/* Call changeArray function */
changeArray(d, array);
for(int i = 0; i < d; i++)
{
for(int j = 0; j < d; j++)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
for(int count = 0; count < d; count++)
{
free(array[count]);
}
return 0;
}
void changeArray(int n, int *array[d])
{
for(int i =0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
array[i][j] = i*j;
}
}
return;
}
The code above works pretty well (it seems), but I've read in the web that using pointer to pointer is not the correct way to create 2D arrays. So I've come up with the following code, which also works:
#include <stdio.h>
#include <stdlib.h>
#define DIM_MAX 9
int d = 3;
void changeArray(int d, int *array[d]);
int main()
{
//alocate array of 'd' colummns and 'd' row using malloc using array of pointers
int *array[DIM_MAX] = {0};
for(int count = 0; count < d; count++)
{
array[count] = (int *)malloc(d*sizeof(int *));
}
/* Call changeArray function */
changeArray(d, array);
for(int i = 0; i < d; i++)
{
for(int j = 0; j < d; j++)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
for(int count = 0; count < d; count++)
{
free(array[count]);
}
return 0;
}
void changeArray(int n, int *array[d])
{
for(int i =0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
array[i][j] = i*j;
}
}
return;
}
What is the difference in using any of the two ways above to write this code?
[Not an answer, but an alternative approach to achieve the desired result, namely defining a user-defined 2D array.]
Assuming the compiler in use supports VLAs you could do this:
#include <stddef.h> /* for size_t */
void init_a(size_t x, size_t y, int a[x][y]); /* Order matters here!
1st give the dimensions, then the array. */
{
for (size_t i = 0; i < x; ++i)
{
for (size_t j = 0; j < y; ++j)
{
a[i][j] = (int) (i * j); /* or whatever values you need ... */
}
}
}
int main(void)
{
size_t x, y;
/* Read in x and y from where ever ... */
{
int a[x][y]; /* Define array of user specified size. */
init_a(x, y, a); /* "Initialise" the array's elements. */
...
}
}
It is actually pretty simple. All you have to do is this:
int i[][];
You are overthinking it. Same as a normal array, but has two indexes.
Let's say you want to create a "table" of 4 x 4. You will need to malloc space for 4 pointers, first. Each of those index points will contain a pointer which references the location in memory where your [sub] array begins (in this case, let's say the first pointer points to the location in memory where your first of four arrays is). Now this array needs to be malloc for 4 "spaces" (in this case, let's assume of type INT). (so array[0] = the first array) If you wanted to set the values 1, 2, 3, 4 within that array, you'd be specifying array[0][0], array[0][1], array[0][2], array[0][3]. This would then be repeated for the other 3 arrays that create this table.
Hope this helps!
I have to be losing my mind here. I'm getting a segfault at the line for(i = 0; i < N; i++) {. I've never encountered anything like this. Here's the full code:
#include <stdio.h>
#include <time.h>
#define N 2400
#define M 2000
#define P 500
int main() {
int a[N][N];
int b[N][N];
int c[N][N];
int i, j;
// Initialize matrix A
for(i = 0; i < N; i++) {
for(j = 0; j < M; j++) {
a[i][j] = j-1+2;
}
}
// Initialize matrix B
for(i = 0; i < M; i++) {
for(j = 0; j < P; j++) {
b[i][j] = i-j+1;
}
}
}
First : you have declared a, b and c as [N][N] matrix, but you initialize them as if they were [N][M] and [M][P] matrix. Considering N > M > P, that should not cause a segfault, but the intent is not clear.
Second, if you replace your defines by :
#define N 10
#define M 5
#define P 2
Your program work. This is because local variables a and b are stored on the stack and your stack is limited in size. Consult your compiler and your system documentation to know exactly the limits imposed.
To avoid such problem, allocate your memory using malloc or equivalent function, that allocate memory on the heap, which is less constrained.
I'm looking to create a program that creates and stores N random complex numbers. However, it's necessary to use another array (of pointers) which points to every element on the complex array. Then, I have to present it sorted by its norm to the user.
To "sort" it, I just change to where the pointer array is pointing to. Then I just show the "sorted" array of pointers.
But I'm not getting it right. How can I achieve this?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#define FORMATLOG "FORMATLOG: invalid parameters: ex3 <N>"
#define RANGE 18 - 6
enum { true, false };
typedef struct {
double real,
imag,
norm;
} Complex;
void generateComplex(int N) {
int i, test;
Complex vector[N];
for(i = 0; i < N; i++) {
vector[i].real = rand() % RANGE;
do { vector[i].imag = rand() % RANGE; } while(vector[i].imag == 0);
vector[i].norm = sqrt(pow(vector[i].real, 2) + pow(vector[i].imag, 2));
}
Complex *p_vect = &vector;
/* makes array point in order */
while(test == false) {
test == true;
for(i = 0; i < N - 1; i++)
if(vector[i].norm > vector[i + 1].norm) {
*p_vect[i] = &vector[i + 1];
*p_vect[i + 1] = &vector[i];
test = false;
}
}
for(i = 0; i < N; i++)
printf("\t%d -| %2g + %2gi | = %g\n", i, vector[i].real,
vector[i].imag,
vector[i].norm);
printf("********************************\n");
for(i = 0; i < N; i++)
printf("\t%d -| %2g + %2gi | = %g\n", i, p_vect[i].real,
p_vect[i].imag,
p_vect[i].norm);
}
int main(int argc, char **argv) {
if(argc != 2) {
puts(FORMATLOG);
return false;
}
srand(time(NULL));
int i, N = atoi(argv[1]);
generateComplex(N);
return true;
}
Complex *p_vect = &vector;
This creates a pointer to the existing array. The requirement is to create an array of pointers, not a pointer to an array.
Complex *p_vect[N];
for (i = 0; i < N; i++) {
p_vect[i] = &vector[i];
}
If you start with this, you can then sort p_vect without touching vector. Your sorting code, when written correctly, will make no mention of vector at all.