这个指针到指针的语句在C中是什么意思?

这个指针到指针的语句在C中是什么意思?,c,pointers,declaration,pointer-to-pointer,C,Pointers,Declaration,Pointer To Pointer,我应该如何解释上述C代码的含义?在中调用malloc(): int **arr = (int **)malloc(r * sizeof(int *)); 为指向int的r指针分配空间,并返回指向分配的void*。然后将该指针转换为int**,并分配给arr,这是指向int的指针。因此,arr指向分配区域的第一个元素,它是指向int的指针。这样的代码可用于创建“锯齿”数组,其中数组的每一行分别分配;这意味着分配在内存中可能不连续,因此这不是真正的2d数组。请参阅以了解更多关于此的信息 不过,上述

我应该如何解释上述C代码的含义?

在中调用
malloc()

int **arr = (int **)malloc(r * sizeof(int *));
为指向
int
r
指针分配空间,并返回指向分配的
void*
。然后将该指针转换为
int**
,并分配给
arr
,这是指向
int
的指针。因此,
arr
指向分配区域的第一个元素,它是指向
int
的指针。这样的代码可用于创建“锯齿”数组,其中数组的每一行分别分配;这意味着分配在内存中可能不连续,因此这不是真正的2d数组。请参阅以了解更多关于此的信息

不过,上述风格被认为是不好的。最重要的是,尽可能避免使用显式类型作为
sizeof
运算符的参数:

int **arr = (int **)malloc(r * sizeof(int *));
如果
arr
的类型在代码生命周期中的某个时间点发生更改,则这不太容易出错,并且更容易维护

此外,此强制转换是多余的,只会使代码变得混乱:

int **arr = (int **)malloc(r * sizeof *arr);
作为最后的改进,在这种情况下,我更愿意将
sizeof
表达式放在第一位:

int **arr = malloc(r * sizeof *arr);
在上述特定情况下,这是一个无用的更改,但如果存在额外的乘法,例如:

int **arr = malloc(sizeof *arr * r);
这保证了算法的执行类型至少与
大小\u t
一样宽,从而降低了整数溢出的风险(
有符号
整数溢出在C中导致未定义的行为),并可能降低
无符号
整数环绕的风险(定义良好,但可能意外或不受欢迎).

这个

int **arr = malloc(sizeof *arr * r * n);
是类型为
int*[r]
的数组的动态分配,该数组是类型为
int*
r
元素数组

< >为了使声明更清楚,请考虑以下简单程序

int **arr = (int **)malloc(r * sizeof(int *));
为了简单起见,在程序中使用了类型
char
,而不是类型
int

表达式中的数组指示符(很少有例外)转换为指向其第一个元素的指针

因此,由于数组
s
的类型是
char*
,那么指向数组
s
的第一个元素的指针的类型将是
char**

对于问题的原始声明,则动态分配一个内存范围,该内存范围被解释为
int*
类型的元素数组。并且将隐含数组的第一个元素将存在的区段的起始地址分配给指针。因此,指针的类型应为int**

Hello user292174
通常,在运行时计算数组的行数和列数时,此类分配用于模拟二维数组

比如说

int **arr = (int **)malloc(r * sizeof(int *));
0 1 2 
3 4 5
如果编译器支持可变长度数组,则可以立即分配二维数组。比如说

int **arr = (int **)malloc(r * sizeof(int *));
0 1 2 
3 4 5
#包括
#包括
内部主(空)
{
尺寸r=2;
尺寸c=3;
int(*arr)[c]=(int**)malloc(sizeof(int[r][c]);
对于(大小i=0;i

porgram输出与上图相同。

问题太广泛,但:
intfoo
声明一个
int
<代码>int*foo
;声明指向
int
的指针<代码>整数**foo声明指向
int*
的指针,即指向
int
的指针。这可能是指向
int
r
指针数组的动态分配。这些指针可能会被用作穷人二维(或更多)ints数组构造的一部分。如果看不到更多的代码,我们就不能更具体。将鼠标悬停在“双指针”标记上,查看为什么不应将其称为“双指针”。“…保证使用大小类型执行算术…”但不能保证在
大小类型中执行算术。根据“…将具有较小整数转换秩类型的操作数转换为具有较大秩的操作数类型…”“…消除整数溢出的风险…”。哦这如何消除整数溢出的风险?如果操作数具有相同的值,则结果将是相同的。“…可能会降低无符号整数环绕的风险…”不是真的。在所有这些方面,您最好的选择是将
r
n
声明为
size\u t
(您无论如何都应该这样做,对吧?),然后。。。你听说过“F”模式吗?这是一张热图,显示了我们大多数眼睛在登上网页的最初几分钟内聚焦的位置。您应该尽量将最有用的信息放在靠近页面左侧的位置。@Sebivor--edited。如果
r
具有较小的转换秩,则使用
size\u t
执行
sizeof*arr*r
,如果
n
具有较小的转换秩,则使用
size\u t
执行第二次乘法。如果
r
n
具有更大的转换等级,则生成的类型将是更宽的类型。整数溢出被删除,因为
无符号
类型不会溢出。但是,我认为一个较大的
有符号的
类型可能会溢出。这确实是一种降低风险的策略,你说得对。嘿,我错过了。。。虽然它非常明确,但强制转换表达式不能是乘法表达式,所以它是从左到右的,正如您所说的。我坚持我的观点,你不应该使用这样的例子
#include <stdio.h>
#include<stdlib.h>

int main(void) 
{
    size_t r = 2;
    size_t c = 3;

    int ( *arr )[c] = (int **)malloc( sizeof( int[r][c] ) );


    for ( size_t i = 0; i < r; i++ )
    {
        for ( size_t j = 0; j < c; j++ )
        {
            arr[i][j] = c * i + j;
        }
    }

    for ( size_t i = 0; i < r; i++ )
    {
        for ( size_t j = 0; j < c; j++ )
        {
            printf( "%d ", arr[i][j] );
        }
        putchar( '\n' );
    }

    free( arr );

    return 0;
}