简体   繁体   English

C 指向整数数组数组的指针

[英]C pointer to array of array of integers

What is the equivalent in C for inizializing a (constant) array of arrays of integers (of different dimensions) ?在 C 中初始化(常量)整数数组(不同维度)的等效项是什么?

In javascript it is like this:在javascript中它是这样的:

myarray=[ [1,2,3,4], [123,234], [1], [1,2] ] myarray=[ [1,2,3,4], [123,234], [1], [1,2] ]

 console.log(myarray=[ [1,2,3,4], [123,234], [1], [1,2] ])

How do I do the same in C?我如何在 C 中做同样的事情?

Example: This in C works:示例:这在 C 中有效:

const unsigned char *cf[] = { "\x2", "\x0,\x1,\x2", "\x3,\x4"};

I wish to do the same but without the quotes.我希望做同样的事情,但没有引号。

putting directly 2, [0,1,2], [3,4]直接输入 2, [0,1,2], [3,4]

I explain better:我解释得更好:

this works:这有效:

int c1[]={1,2,3,4};
int c2[]={5,6};
int c3[]={2,3,4}

int *arr[]={c1,c2,c3};

so I can access every element as arr[0][x] arr[1][x]所以我可以访问每个元素作为arr[0][x] arr[1][x]

now i have a big array.现在我有一个大数组。 how can I initialize it?我该如何初始化它?

const unsigned char *cf[] = { "\x2", "\x0,\x1,\x2", "\x3,\x4"};

I wish to do the same but without the quotes.我希望做同样的事情,但没有引号。


Code could use compound literals to form the small unsigned char arrays.代码可以使用复合文字来形成小的unsigned char数组。 Yet cf[] (an array of pointers to unsigned char ) loses knowledge of how big each array.然而cf[] (指向unsigned char的指针数组)不知道每个数组有多大。

Not quite an "array of arrays of integers of different dimensions".不完全是“不同维度的整数数组的数组”。

int foo() {
  const unsigned char *cf[] = {
      (unsigned char[]) { 2, ',', 0 }, 
      (unsigned char[]) { 0, ',', 1, ',', 2, 0 }, 
      (unsigned char[]) { 3, ',', 4, 0 }
  };
  return cf[0][0];
}

Note: "\\x2" is 2 bytes long.注意: "\\x2"是 2 个字节长。
"\\x0,\\x1,\\x2" is 6 bytes long. "\\x0,\\x1,\\x2"是 6 个字节长。
"\\x3,\\x4" is 4 bytes long. "\\x3,\\x4"是 4 个字节长。

` `

What is the equivalent in C... C中的等价物是什么...

The short answer is there is nothing equivalent in C for doing what you are showing in javascript .简短的回答是,在 C 中没有任何等效的东西来执行您在javascript中显示的内容。

The most common way to do something similar in C is to use a struct:在 C 中做类似事情的最常见方法是使用结构:

typedef struct {
   int a[4];
   int b[2];
   int c[1];
   int d[2];
} ARR;

const ARR arr = {{1,2,3,4}, {123, 234}, {1}, {1,2}};

C99 (and beyond) implements flexible array members . C99(及更高版本)实现了灵活的数组成员 This is similar, but again, not exactly what you want.这是相似的,但同样,不完全是你想要的。 ( ie it also uses the struct construct.) (即它也使用struct构造。)

There's no easy way to do it and it depends if you know exactly your input.没有简单的方法可以做到这一点,这取决于您是否确切地知道您的输入。

What I did was to store N + 1 size for the int *nums and then store the total length in the first memory position.我所做的是为int *nums存储 N + 1 大小,然后将总长度存储在第一个内存位置。

#include <stdio.h>
#include <stdlib.h>
#define SIZE_ARRAY 4

struct myArray{
  int *nums;  
};

int main()
{
    struct myArray myArrays[SIZE_ARRAY];
    myArrays[0].nums = malloc(sizeof(int) * 5);
    *(myArrays[0].nums) = 4;//the size of the allocated memory
    *(myArrays[0].nums + 1) = 1;
    *(myArrays[0].nums + 2) = 2;
    *(myArrays[0].nums + 3) = 3;
    *(myArrays[0].nums + 4) = 4;

    myArrays[1].nums = malloc(sizeof(int) * 3);
    *(myArrays[1].nums) = 2;//the size of the allocated memory
    *(myArrays[1].nums + 1) = 123;
    *(myArrays[1].nums + 2) = 234;

    myArrays[2].nums = malloc(sizeof(int) * 2);
    *(myArrays[2].nums) = 1;//the size of the allocated memory
    *(myArrays[2].nums + 1) = 1;

    myArrays[3].nums = malloc(sizeof(int) * 3);
    *(myArrays[3].nums) = 2;//the size of the allocated memory
    *(myArrays[3].nums + 1) = 1;
    *(myArrays[3].nums + 2) = 2;

    printf("[");
    for(int i = 0; i < SIZE_ARRAY; ++i)
    {
        printf("[");
        for (int j = 0; j < *(myArrays[i].nums); ++j)
        {
            printf("%d", *(myArrays[i].nums + j + 1));

            if (j < *(myArrays[i].nums) - 1)
            {
                printf(", ");
            }
        }

        printf("]");

        if (i < SIZE_ARRAY - 1)
        {
            printf(", ");
        }
    }
    printf("]");

    return 0;
}

It gives the expected output but it's not as flexible as the javascript code.它提供了预期的输出,但不如 javascript 代码灵活。

The difficulty in C is that there is no in-built data type that stores a heterogeneous list of elements. C 语言的难点在于没有存储异构元素列表的内置数据类型。 But of course, C being C, you can build something up yourself using pointers and structs, like my example below.但是当然,C 是 C,你可以使用指针和结构自己构建一些东西,就像我下面的例子。 The nasty implementation detail is that you need some way to store the size of each of your arrays, hence the need for a struct.令人讨厌的实现细节是您需要某种方式来存储每个数组的大小,因此需要一个结构。

#include <stdio.h>

typedef struct container_t
{
  int size;
  int *item;
} container_t;

int main(void)
{  
  int a[] = {1,2,3,4};
  int b[] = {123,234};
  int c[] = {1};
  int d[] = {1,2};
  container_t s[] = {
                      {sizeof(a)/sizeof(a[0]), a},
                      {sizeof(b)/sizeof(b[0]), b},
                      {sizeof(c)/sizeof(c[0]), c},
                      {sizeof(d)/sizeof(d[0]), d}
                    };

  for(int i = 0; i < sizeof(s)/sizeof(s[0]); i++)
  {    
    printf("[");
    for(int j = 0; j < s[i].size; j++)
      printf("%d,", s[i].item[j]);
    printf("]\r\n");
  }
}

Output:输出:

[1,2,3,4,] [1,2,3,4,]

[123,234,] [123,234,]

[1,] [1,]

[1,2,] [1,2,]

Assuming syntax is the issue here (and not performance), you could try to create this from scratch.假设语法是这里的问题(而不是性能),您可以尝试从头开始创建它。

In both cases the syntax is slightly more complicated than in your Javascript code.在这两种情况下,语法都比您的 Javascript 代码稍微复杂一些。 I'm not sure how much shorter one can make this in C, but you could probably make it a bit easier to read in C++.我不确定在 C 中可以缩短多少,但是您可能可以使其在 C++ 中更容易阅读。

Still, I provide 2 approaches below.不过,我在下面提供了两种方法。 Either by using variable arguments to handle the creation of smaller arrays or by parsing an array of strings, which is arguably even easier to read, but probably a bit slower.通过使用可变参数来处理较小数组的创建或通过解析字符串数组,这可以说更容易阅读,但可能会慢一点。

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

// I don't know what type you had in mind...
typedef int type_t;
#define type_t_specifier "%d"

typedef struct tab { // Helper struct
    type_t* data;
    size_t size;
} tab;

tab ctb(size_t size, ...) { // Parse one of the subarrays into the temporary struct
    tab res;
    res.size = size;
    res.data = (type_t*)malloc(res.size * sizeof(type_t));
    va_list valist;
    va_start(valist, size);
    for (int i = 0; i < size; i++) {
        res.data[i] = va_arg(valist, int);
    }
    return res;
}

typedef struct array_t { // Array struct
    type_t** data;
    size_t* sizes;
} array_t;

array_t create_array1(size_t size, ...) { // Create the array using variable arguments
    array_t array;
    array.data = (type_t**)malloc(size * sizeof(type_t*));
    array.sizes = (size_t*)malloc((size + 1) * sizeof(size_t));
    array.sizes[0] = size;
    va_list valist;
    va_start(valist, size);
    for (int i = 0; i < size; i++) {
        tab temp = va_arg(valist, tab);
        array.data[i] = (type_t*)malloc(temp.size * sizeof(type_t));
        array.sizes[i + 1] = temp.size;
        array.data[i] = temp.data;
    }
    return array;
}

array_t create_array2(size_t size, const unsigned char** temp) { // Or you can simply parse an array of strings instead
    array_t array;
    array.data = (type_t**)malloc(size * sizeof(type_t*));
    array.sizes = (size_t*)malloc((size + 1) * sizeof(size_t));
    array.sizes[0] = size;
    for (int i = 0; i < size; i++) {
        int nsize = 1;
        for (int j = 0; temp[i][j] != '\0'; j++) {
            if (temp[i][j] == ',') {
                nsize++;
            }
        }
        array.data[i] = (type_t*)malloc(nsize * sizeof(type_t));
        array.sizes[i + 1] = nsize;
        int start = 0;
        int cnt = 0;
        for (int j = 0; j <= strlen(temp[i]); j++) {
            if (temp[i][j] == ',' || temp[i][j] == '\0') {
                sscanf(&(temp[i][start]), type_t_specifier, &array.data[i][cnt++]);
                start = j + 1;
            }
        }
    }
    return array;
}

void delete_array(array_t array) { // Clean up the array
    for (int i = 0; i < array.sizes[0]; i++) {
        free(array.data[i]);
    }
    free(array.data);
    free(array.sizes);
}

void print_array(array_t array) { // Just to check if it works
    for (int i = 0; i < array.sizes[0]; i++) {
        for (int j = 0; j < array.sizes[i + 1]; j++) {
            fprintf(stderr, type_t_specifier, array.data[i][j]);
            if (j != array.sizes[i + 1] - 1) fprintf(stderr, " ");
            else fprintf(stderr, "\n");
        }
    }
}

int main(void) {
    array_t myarray;
    // You can either complicate the syntax a tiny bit by providing the lengths of each of the subarrays
    myarray = create_array1(4, ctb(4, 1, 2, 3, 4), ctb(2, 123, 234), ctb(1, 1), ctb(2, 1, 2));
    print_array(myarray);
    delete_array(myarray);
    // Or parse an array of strings to create your array
    const unsigned char* temp[] = { "1,2,3,4", "123,234", "1", "1,2" };
    myarray = create_array2(4, temp);
    print_array(myarray);
    delete_array(myarray);
    return 0;
}
// We need to parse the size of the outer array in both cases.

One way this could be improved for performance would also be to store the memory contiguously.可以提高性能的一种方法也是连续存储内存。 This would make later use faster but probably cost a bit more time when constructing the array.这将使以后使用更快,但在构造数组时可能会花费更多时间。

Or if you wanted to make it even easier to work with you could simply parse your original javascript array.或者,如果您想让它更容易使用,您可以简单地解析您的原始 javascript 数组。 Though I really would avoid parsing strings if possible.如果可能的话,我真的会避免解析字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM