Create 2D array from existing 1D arrays in C?

In perl, I can create 1D arrays and then create a 2D array from them like this:

@a1=(a,b,c)
@a2=(d,e,f)
@a3=(g,h,i)
@m23_v1=(\@a1,\@a2,\@a3)

      

Here's another way (assuming that @a1

, @a2

and @a3

are the same as in the previous example):

@m23_v2=([@a1],[@a2],[@a3])

      

The difference between the two is that when using backslashes, the change $a[0][0]

will also change $a1[0]

. On the other hand, when parentheses are used, the value is copied, so the change $a[0][0]

will not change $a1[0]

. Below are the memory addresses of the variables, which should clarify what I mean:

print \$a1[0]
SCALAR(0x2006c0a0)

print \$m23_v1[0][0]
SCALAR(0x2006c0a0)

print \$m23_v2[0][0]
SCALAR(0x2030a7e8)

      

How to achieve the same but in C? I've tried the following code:

# include <stdio.h>
int main(){
  int a1[3] = {1,2,3};
  int a2[3] = {4,5,6};
  int m23[2][3] = {a1, a2};
  printf("%d\n", a1[0]);
  printf("%d\n", m23[0][0]);
}

      

But it gives me the following compilation warnings:

2d.c: In functionmain’:
2d.c:4:3: warning: initialization makes integer from pointer without a cast [enabled by default]
2d.c:4:3: warning: (near initialization form23[0][0]’) [enabled by default]
2d.c:4:3: warning: initialization makes integer from pointer without a cast [enabled by default]
2d.c:4:3: warning: (near initialization form23[0][1]’) [enabled by default]
2d.c:5:3: warning: incompatible implicit declaration of built-in functionprintf[enabled by default]

      

Once executed, the C code returns the following:

1
-1077371888

      

Questions:

  • Why am I getting compilation warnings and how can I modify the code to get rid of them?
  • If the given C is equivalent to the backslashed perl version, then what is the equivalent for the parenthesis version (and vice versa)?
  • Why am I getting -1077371888 instead of 1?
+3


source to share


6 answers


You can use an array of pointers to get the equivalent backslahed version (i.e. @m23_v1

):

#include <stdio.h>

int main(void)
{
    int a1[3] = {1,2,3};
    int a2[3] = {4,5,6};

    int *m23[2] = {a1, a2};

    printf("%d\n", a1[0]);
    printf("%d\n", m23[0][0]);

    return 0;
}

      

In your code:

int m23[2][3] = {a1, a2};

      

The initializer expects to be filled with integers. Basically you are creating a two-dimensional array with two integers: a1

, a2

. The rest of the elements are zero-initialized. To illustrate this, it looks something like this:

int m23[2][3] = {0xaaee33, 0xaaee55, 0, 0, 0, 0};

      



which is actually the same as:

int m23[2][3] = {{0xaaee33, 0xaaee55, 0}, {0, 0, 0}}; // two rows, three columns

      

However, a1

it is not an integer. This is the name of the array that is implicitly converted to int

(after converting it to a pointer that points to the first element of the array). In other words, you are implicitly converting addresses to a1

and a2

to two integers. In fact, such an operation is illegal in C, and such code doesn't even compile with a flag -pedantic-errors

(or equivalent).

what is the equivalent for the parenthesis version (and vice versa)?

The skew equivalent defines a multidimensional array of a specific size and then copies each element of the arrays into it a1

and a2

:

#include <stdio.h>
#include <string.h>

int main(void)
{
    int a1[3] = {1,2,3};
    int a2[3] = {4,5,6};

    int m23[2][3];
    memcpy(m23 + 0, a1, sizeof(a1));
    memcpy(m23 + 1, a2, sizeof(a2));

    printf("%d\n", a1[0]);
    printf("%d\n", m23[0][0]);

    return 0;
}

      

+1


source


You get a warning because when you initialize the array m23

, the arrays are in a1

and out a2

for pointers, which makes the array massive, but not pointer. And also how do you solve your problem by declaring m23

as an array of pointers:



int *m23[2] = { a1, a2 };

      

+3


source


Well, you cannot initialize an array using another array. You can do it like this:

int m[2][3] = {{1,2,3},{4,5,6}};

      

This is because a1 and a2 are treated as a pointer to int. This can be done using an array of pointers:

int* m[2] = {a1,a2);

      

+1


source


  • Why am I getting compilation warnings and how can I modify the code to get rid of them?

This is because you are assigning a pointer (a1) where it expects an integer (m23 if from type int) without casting correctly.

This is one way to write it:

#include <stdio.h>
#define N 2
#define M 3
int main(){
    int a1[M] = {1,2,3};
    int a2[M] = {4,5,6};
    int* m23[N] = {a1, a2};
    printf("%d\n", a1[0]);
    printf("%d\n", m23[0][0]);
}

      

  1. If the given C is equivalent to the backslashed perl version, then what is the equivalent for the parenthesis version (and vice versa)?

I'm not a Perl expert, but I think there is no way as easy as some types. As you can see in your Perl release, you are printing where the string and vector are in memory. $ a1 is the same as $ m23_v1 since it gets $ a1 for the string, but in $ m23_v2 you are actually creating another vector from $ a2, so the memory location changes.

  1. Why am I getting -1077371888 instead of 1?

This is because you assigned m23 the value of the pointer a1, which is an address in memory, and when printed as an integer (printf ("% d \ n") it gets an int value and that is the result.

+1


source


As other answers have said, you can make an array of pointers to collect both sub-arrays together. They are not really copied, however, but simply referenced (like a Perl snippet with backslashes).

int *m23[] = {a1, a2};

      

In C, you cannot assign arrays, and you cannot directly initialize an array from another. You have to copy it manually:

int a1[3] = {1,2,3};
int a2[3] = {4,5,6};

// Uninitialized array of sufficient size
int m23[2][3];

// Manual copy of both subarrays
memcpy(&m23[0], &a1, sizeof a1);
memcpy(&m23[1], &a2, sizeof a2);

      

Side note related to one of your comments: arrays are not pointers, constants, or others. But the name of an array can decay into a pointer to its first element in most contexts.
Exceptions to pointer array decay include the operator sizeof

used above: its result here 3 * sizeof(int)

, the actual size of the array, not sizeof(int*)

.

+1


source


You should consider the way C is used to store multidimensional arrays in memory.

C is a simple thinking language, and it thinks that in an array of n dimensions, only the latter determines how many real objects are present, others repeat it. That is, an array of int int arr[10][5];

means that we have a string of 5 integers, which is repeated 10 times in memory.

If we add more dimensions, we get more repetitions in memory. That is int arr[4][10][5];

, it means that we have a string of 5 integers, which is repeated 10 times, summing 50 integers in a row, which is repeated 4 times again. At the end, we have a sequence of 200 integers contiguous in memory, representing a three-dimensional array of integers. Now, one of the dark sides of C is that, without bounds control, this array can be read at any index we like that is between 0 and 199. For this reason, when you declare a multidimensional array, to allow the compiler to handle correctly to the elements, you must specify all sizes except the last one.

Now with your problem, you can use join to fake an array mix:

union
{
    struct
    {
      int a1[3];
      int a2[3];
    };
    int m23[2][3];
} stTst = {1,2,3,4,5,6};

printf("%d\n", stTst.a1[0]);
printf("%d\n", stTst.m23[0][0]);
printf("%d\n", stTst.a2[2]);
printf("%d\n", stTst.m23[1][2]);

      

In this case, we are using the C array memory layout to create two dimensional arrays and mutimeric together.

Another solution is to copy each individual array in multidimensional dimension.

+1


source







All Articles