【问题标题】:Why A[2][3] is valid lvalue for the declaration int *A [10];为什么 A[2][3] 是声明 int *A [10] 的有效左值;
【发布时间】:2020-02-07 09:47:43
【问题描述】:
int *A [10];

为什么A[2][3] 是一个有效的左值。正如我在A[2] 中理解的那样,我们存储了一个指向整数的指针(单个整数不是数组)。那么[3]中的A[2][3]如何访问呢?

【问题讨论】:

  • 代码为什么要这样做?
  • 这是一道作业题?
  • C 没有边界检查。指向单个int 值的指针可以被视为单个元素的数组,超出任何数组的范围都会导致未定义的行为。您的程序有责任不超出范围。
  • @Someprogrammerdude 那么拥有 int * 类型有什么好处?
  • 没有。第一个 (int *A[10];) 将 A 声明为一个包含十个指向 int 的指针的数组。第二个 (int[] *A [10];) 语法无效。如果指向单个值或数组第一个元素的指针是程序逻辑的一部分,编译器本身并不关心(它甚至不知道)。您可能应该花一些时间阅读几本书以了解有关指针和数组的更多信息,或者请老师/导师帮助您(stackoverflow.com 不是辅导网站)。

标签: c arrays pointers multidimensional-array


【解决方案1】:

希望这段代码可以演示如何使用 int 指针数组。

目标是创建一个足以容纳 30 个整数的缓冲区。然后将一个 int 指针分配给分配的缓冲区的每个第 3 个地址分区。

所以如果 a[0] 设置为地址 0x562437eea260。 那么这意味着 a[1] 将被设置为地址 0x562437eea26c 大约 (sizeof(int) * 3), 12, bytes 远。

然后可以通过调用a[i][j]来设置指针地址处的值;假设 i 是从 int 指针数组中选择地址的索引,j 是 1、2 或 3,具体取决于您希望访问的数字。

预期输出:

a[0] = 0x562437eea260
a[0][0] = 2
a[0][1] = 3
a[0][2] = 5

a[1] = 0x562437eea26c
a[1][0] = 3
a[1][1] = 3
a[1][2] = 7

a[2] = 0x562437eea278
a[2][0] = 9
a[2][1] = 2
a[2][2] = 3

在我的示例中,我将所有整数设置为随机值

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define UNUSED(x)((void)(x))

#define TOTAL_INT_POINTERS 10
#define INTS_PER_POINTER 3

int main(const int argc, const char** const argv, const char** const envp) {
    UNUSED(argc); UNUSED(argv); UNUSED(envp);

    // Seed random number generator
    srand((unsigned int)time(0));

    // Create and array that will hold 10 int pointers
    int *a[TOTAL_INT_POINTERS] = {0};

    // Allocate memory for integers
    int *ptr = (int *)malloc((sizeof(int) * TOTAL_INT_POINTERS) * INTS_PER_POINTER);
    if(ptr == NULL) {
        fprintf(stderr, "Failed to allocate memory for integers!\n");
        return (int)EXIT_FAILURE;
    }

    // Assign pointers and values to each allocated space
    for(unsigned int i = 0; i < TOTAL_INT_POINTERS; i++) {
        // Assign pointer array member
        a[i] = ptr + (i * INTS_PER_POINTER);

        // Print assigned address
        printf("a[%d] = %p\n", i, a[i]);

        // Give 3 integers their values and print out the result
        for(unsigned int j = 0; j < INTS_PER_POINTER; j++) {
            a[i][j] = rand() % 10;
            printf("a[%d][%d] = %d\n", i, j, a[i][j]);
        }

        putchar('\n');
    }

    // Free up used memory
    free(ptr);

    return (int)EXIT_SUCCESS;
}

【讨论】:

    【解决方案2】:

    正如 cmets 中已经指出的,编译器只管理指针,并不知道数据的实际结构。您可以使用方括号或使用指针算法通过索引访问数组元素:

    A[i][j] 等价于*(A[i] + j) 也等价于*(*(A+i) + j)

    请注意,您必须确保您正在访问的内存实际上在数组范围内。

    延伸阅读:

    【讨论】:

      【解决方案3】:

      x 指向 int 的事实并不意味着在该 int 旁边没有更多的int,无论是在它之前还是之后或两者兼而有之。

      如果我有一个数组int a[10],那么&amp;a[5] 指向数组的第5 个元素,&amp;[5] - 1&amp;a[5] + 1 指向第4 和第6 个元素。如果我将&amp;a[5] 作为它的子程序传递给子程序参数int *x,并且该子程序知道其他元素存在,它可以使用x[1]引用数组的第6个元素,x[-1]引用第4个元素。

      给定int *A[10],我可以根据需要分配尽可能多的内存并将其地址分配给A[0]。然后A[0][0] 指向该内存中第一个int 的空间,A[0][1] 指向下一个int 的空间,依此类推。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-17
        • 1970-01-01
        • 2022-01-24
        • 2020-02-15
        • 2011-09-07
        • 1970-01-01
        • 1970-01-01
        • 2016-05-03
        相关资源
        最近更新 更多