【问题标题】:access c multidemensional array with only one argument?只用一个参数访问 c 多维数组?
【发布时间】:2017-12-06 04:10:33
【问题描述】:

我正在阅读这段 C 代码,我发现很难理解发生了什么。

这是数组:

static const char   gradient[32][4] =
{
{ 1,  1,  1,  0}, { 1,  1,  0,  1}, { 1,  0,  1,  1}, { 0,  1,  1,  1},
{ 1,  1, -1,  0}, { 1,  1,  0, -1}, { 1,  0,  1, -1}, { 0,  1,  1, -1},
{ 1, -1,  1,  0}, { 1, -1,  0,  1}, { 1,  0, -1,  1}, { 0,  1, -1,  1},
{ 1, -1, -1,  0}, { 1, -1,  0, -1}, { 1,  0, -1, -1}, { 0,  1, -1, -1},
{-1,  1,  1,  0}, {-1,  1,  0,  1}, {-1,  0,  1,  1}, { 0, -1,  1,  1},
{-1,  1, -1,  0}, {-1,  1,  0, -1}, {-1,  0,  1, -1}, { 0, -1,  1, -1},
{-1, -1,  1,  0}, {-1, -1,  0,  1}, {-1,  0, -1,  1}, { 0, -1, -1,  1},
{-1, -1, -1,  0}, {-1, -1,  0, -1}, {-1,  0, -1, -1}, { 0, -1, -1, -1},
};

它是 32*4,这是试图访问这个数组的另一部分代码:

const char * g0000 = gradient[Indice (x1, y1, z1, t1)];

Indice 是一个返回 int 的函数。那么这个g0000 是什么(我知道它是一个指针),比如说Indice 返回1,那么g0000 的值是多少?我主要用 C# 编写代码,据我了解,如果你想访问多维数组,你需要几个参数,但这里只有一个,我真的很困惑......

【问题讨论】:

  • 如果A是一个二维数组,那么A[n]是数组的第n行(从0开始)
  • @M.M 有道理,谢谢!
  • 那是一些非常的垃圾代码。首先表格应该输入signed char!! 那个代码的作者应该去写Visual Basic。

标签: c arrays pointers


【解决方案1】:

gradient 的类型是static const char[32][4],即二维字符数组。当您使用 [] 运算符取消引用它两次时,您会得到一个 char

但在这种情况下,当你只服从一次你得到const char[4] 时,它可以衰减为const char* 并分配给g0000

准确地说,如果Indice(x1, y1, z1, t1) 返回 1,g0000 将保存第二个子数组的地址。

【讨论】:

    【解决方案2】:

    静态多维数组作为一维数组存储在内存中的方式(在 C 中)。

    例如,如果您有以下数组:

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

    内存分配与中完全相同:

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

    这可以通过下面的sn-p来表示:

    int ray[2][2] = {1, 2, 3, 4};
    int *rayP = (int *) ray;
    printf("%d\n", rayP[3]);     //PRINTS 4
    

    您可以使用多个索引的原因只是 C 让您更轻松地将其用作 2D 数组抽象。

    因此,如果您访问数组 ray[a][b] 的元素 ray[x][y],您实际访问的元素是 ray[x * b + y],尽管 C 不允许您这样做以保持抽象清晰。

    相反,如果您尝试直接访问元素ray[x],它将返回&ray[x * b],这正是您想要的:

    指向所需子数组开头的指针,您可以将其视为数组。

    【讨论】:

    • 误导,因为:1) int 的二维数组是数组的数组,而不是 int 的数组,以及 2) 您不能像访问一维数组一样合法地访问二维数组.
    • 请注意,这种访问是否合法存在争议(尽管每个人都同意在 int *rayP = (int *)&ray; 之后,然后 rayP[3] 是可以的)
    • @M.M -- “虽然每个人都同意” -- 这看起来像是一个严格的别名违规,因为 int *int (*)[] 不是兼容的类型。
    • @DavidBowling 这些类型都与严格别名无关。规则是T 类型的对象只能由T 类型的左值访问(还有一些例外)。在这段代码中,通过int 类型的左值可以访问int 对象,仅此而已。没有int *对象被别名,也没有数组对象的访问(这在C中甚至不可能,只能访问数组元素)
    • @Stargateur 您链接到的问题是关于访问数组的边界,这与严格的别名无关。使用粗体字不会将错误的语句变为正确的语句。
    【解决方案3】:

    假设Indice() 返回gradient 中包含x1, y1, z1 and t1 4 个值的行的索引并不是不合理的。

    gradientconst char[32][4],比如Indice 返回一个索引i 用于gradient

    gradient[i] 
    

    是指向 char 的地址; gradient[i]的计算地址

    g0000 = gradient[i]
    

    gradient + ( i*4*sizeof(gradient[0][0]) )
    

    即指向地址&gradient[i][0]处梯度的第一个元素

    在 C 中没有自动控制数组越界索引,并且在该数组中,访问 [R][C] 就像访问 [R*4+C],这意味着 g0000 指向 [4] 字符区域,您可以尝试访问超过 4 个限制(例如 [i][5])并访问下一行(因为它是 [i*4+5][i+1][1])。

    但是越界访问数组会导致未定义的行为(如果 i+1 > 31 在这种情况下,因为数组 [X] 会从 [0] 变为 [X-1])。

    【讨论】:

    • gradient[i] 是一个数组,而不是一个指针。还有你的地址表达有误,x[y]相当于*(x + y),没有额外的sizeof步骤
    猜你喜欢
    • 1970-01-01
    • 2020-02-01
    • 2019-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-12
    • 1970-01-01
    相关资源
    最近更新 更多