指针指向指针的单个malloc调用;数组";导致无效写入

指针指向指针的单个malloc调用;数组";导致无效写入,c,arrays,pointers,C,Arrays,Pointers,我在这里试图做的(出于教育目的)是让指针指向一个行为类似于数组但只有一个内存分配的指针。Valgrind正在抱怨这段代码,如果我使用多个分配执行更长版本的代码,我在gdb中调试时就会出现segfaults 它分配144字节(3个指针24字节,整数3*40字节)。l[0]是l的+24字节,l[1]是l[0]的+40字节,依此类推 有人能告诉我我做错了什么吗 gcc-o程序-g-ansi-Wpedantic-Wall-Wextra main.c #include <stdlib.h> #

我在这里试图做的(出于教育目的)是让指针指向一个行为类似于数组但只有一个内存分配的指针。Valgrind正在抱怨这段代码,如果我使用多个分配执行更长版本的代码,我在gdb中调试时就会出现segfaults

它分配144字节(3个指针24字节,整数3*40字节)。l[0]是l的+24字节,l[1]是l[0]的+40字节,依此类推

有人能告诉我我做错了什么吗

gcc-o程序-g-ansi-Wpedantic-Wall-Wextra main.c

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

int main(void) {
    int **l;
    int i, j, k;
    int x = 3;
    int y = 10;
    size_t size_y = sizeof(int) * y;
    size_t x_ptrs = x * sizeof(int*);
    size_t mem_to_alloc = x_ptrs + x * size_y;

    l = malloc(mem_to_alloc);

    l[0] = (int*)l + x_ptrs;
    l[1] = (int*)l + x_ptrs + size_y;
    l[2] = (int*)l + x_ptrs + size_y * 2;

    k = 0;
    for(i = 0; i < x; i++)
    for(j = 0; j < y; j++) 
        l[i][j] = (-k++)*12; /* just some number */

    for(i = 0; i < x; i++) {
        for(j = 0; j < y; j++) {
            printf("%.3d\n", l[i][j]);
        }
        puts("");
    }

    free(l);
    l = NULL;
    return 0;
}

当您添加一个整数和一个指针时,该整数将按指针指向的大小放大。所以

l[1] = (int*)l + x_ptrs + size_y;
l[1]
设置为
40*sizeof(int)
过去的
l
字节,即
160
过去的
l
。由于只分配了
144
字节,因此超出了数组边界


这种自动缩放允许您使用指针算法逐步遍历数组,例如
ptr++
,以到达
ptr
指向的数组的下一个元素。

错误可能与此有关

当你在做
l[0]=(int*)l+x_ptrs
,偏移量
x_ptrs
是一个字节数。相反,它应该是您要跳过的整数数,因为
l
被强制转换为
int*

你能试试
l[0]=(int*)l+2*x?如果
int*
(最有可能为8)的大小是
int
(最有可能为4)大小的两倍,则应该可以使用。同样的逻辑也适用于
size\u y

l[0] = (int*)l + 2*x;
l[1] = (int*)l + 2*x + y;
l[2] = (int*)l + 2*x + 2*y;

您应该从使用正确的变量名开始。像
l[i][j]
这样的语句实际上是不可读的。l[0]是l的+24字节->这个语句是错误的
l
l[0]
@ex0ns有相同的地址。他说的是分配给
l[0]
的内容,而不是它的地址。首先,它不会像你所期望的那样工作。其次,为什么不使用一个简单的指针,然后使用简单的数学来获得正确的索引?例如,
int*matrix=malloc(xsize*ysize*sizeof(int));矩阵[x*ysize+y]=5不要!可以使用2D数组,也可以将数组分为两部分:指针数组和其余部分。一个问题是您可能会遇到对齐问题。
l[0] = (int*)l + 2*x;
l[1] = (int*)l + 2*x + y;
l[2] = (int*)l + 2*x + 2*y;