C 为什么是dd++/d++;在(非动态分配的阵列)中不工作?

C 为什么是dd++/d++;在(非动态分配的阵列)中不工作?,c,pointers,multidimensional-array,implicit-conversion,pointer-arithmetic,C,Pointers,Multidimensional Array,Implicit Conversion,Pointer Arithmetic,嘿,我是C语言的初学者,我正在努力理解指针 我创建了一个程序,在该程序中,我在数组arr1中衰减一个指针d,然后在d pointer中释放一个指向指针dd的指针。 我的目的是在非动态分配的数组中使用指针对指针打印单词。 第一个程序打印所有单词 第二个程序只打印第一行 第三个程序打印第一行和一些奇怪的符号 我知道这是一种不寻常的方式,但我很好奇为什么d++或dd++不能在非动态分配的数组中工作 第一个节目 #include<stdio.h> #include<stdlib.h&g

嘿,我是C语言的初学者,我正在努力理解指针 我创建了一个程序,在该程序中,我在数组arr1中衰减一个指针d,然后在d pointer中释放一个指向指针dd的指针。 我的目的是在非动态分配的数组中使用指针对指针打印单词。 第一个程序打印所有单词 第二个程序只打印第一行 第三个程序打印第一行和一些奇怪的符号 我知道这是一种不寻常的方式,但我很好奇为什么d++或dd++不能在非动态分配的数组中工作

第一个节目

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


int main()
{
    int i=0;
    char arr1[5][10]={"ball","wall","window","table","tv"};
    

    printf("\n");



    char *d;
    char **dd=&d;
    for(i=0; i<5; ++i){
        d=arr1[i];
        printf("array[%d] contains: %s\n", i, *dd);
    }

return 0;
}
#包括
#包括
int main()
{
int i=0;
char arr1[5][10]={“球”、“墙”、“窗”、“桌子”、“电视”};
printf(“\n”);
char*d;
字符**dd=&d;

for(i=0;i
dd
从指向
d
开始。d
的**值
arr1
的地址,因此当您取消引用
dd`时,您会得到一个指向数组开头的指针,您可以使用该指针打印单词“ball”。这很好

但是,当您第一次使用
dd++
递增
dd
时,它将指向
d
之后的位置。该位置与数组无关,并且该位置没有
char*
,因此取消引用
dd
是未定义的

换句话说,
dd++
没有意义,因为
d
是单个字符指针


顺便说一句:请注意,您的循环中还有两个
dd++

在第一个程序中,for循环每次迭代中的指针
d
都被分配了数组arr1中存储的每个字符串的第一个字符的地址

for(i=0; i<5; ++i){
    d=arr1[i];
    ^^^^^^^^^^
    printf("array[%d] contains: %s\n", i, *dd);
}
这个语句在循环中

    d++; 
不会影响指针
dd
,因为在递增指针
dd
后,它不会指向指针
d

在第三个程序中也存在同样的问题,即在for loo中增加指针dd之后

for(dd=&d ; *dd ; dd++)
它指向指针d之外的内存,并使用表达式*dd调用未定义的行为

d=&arr1[0][0];
char **dd;
dd=&d;
for(dd=&d ; *dd ; dd++)
                  ^^^^
{
    printf("\nthe words are %s",*dd); 
    d++; 
}
可以使用以下方法使用指针指向存储在二维字符数组中的输出字符串

#include <stdio.h>

int main(void) 
{
    enum { N = 10 };
    char arr1[][N] = { "ball", "wall", "window", "table", "tv" };
    
    const size_t M = sizeof( arr1 ) / sizeof( *arr1 );
    
    for ( char ( *d )[N] = arr1; d != arr1 + M; ++d )
    {
        puts( *d );
    }
    
    return 0;
}
也就是说,表达式中使用的数组指示符(很少有例外)被转换为指向其第一个元素的指针

由于数组
arr1
的类型为
char[5][10]
,因此数组的元素类型为
char[10]
。指向此类对象的指针的类型为
char(*)[10]
。递增指针将指向数组的下一个元素。取消引用演示程序中显示的指针

puts( *d );

我们得到的定点元素是
char[10]
类型的数组。但在表达式中使用,例如,作为puts调用的参数,它反过来被转换为指向数组第一个元素(字符串)的指针还有类型
char*

@4386427我明白你说的话我没有注意到我服用了2倍的dd+,现在我澄清一下你的文本询问
d++
,但那不在你的代码中…!@4386427对不起,我现在编辑了我明白你说的话,但我注意到你使用的是
const size\u t
而不是
 size_t
为什么这样做?@Βill97由于数组arr1的大小是固定的,因此自然会将变量M声明为常量变量,因为数组的大小在程序中不会更改。
#include <stdio.h>

int main(void) 
{
    enum { N = 10 };
    char arr1[][N] = { "ball", "wall", "window", "table", "tv" };
    
    const size_t M = sizeof( arr1 ) / sizeof( *arr1 );
    
    for ( char ( *d )[N] = arr1; d != arr1 + M; ++d )
    {
        puts( *d );
    }
    
    return 0;
}
ball
wall
window
table
tv
puts( *d );