【问题标题】:why dd++/d++ does not work in (non dynamically allocated arrays)?为什么 dd++/d++ 在(非动态分配的数组)中不起作用?
【发布时间】:2021-08-19 12:30:16
【问题描述】:

嘿,我是 C 的初学者,我正在尝试理解指针 我创建了一个程序,在该程序中衰减数组 arr1 中的指针 d,然后在 d 指针中衰减指向指针 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;
}

第二个节目

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


int main ()
{
    
    int i=0;
    char arr1[5][10]={"ball","wall","window","table","tv"};
    printf("\n");
    char *d;
    d=&arr1[0][0];
    char **dd;
    dd=&d;
    for(dd=&d ; *dd ; dd++)
    {
        printf("\nthe words are %s",*dd); 
        d++; 
    }
    
    
    return 0;
}

第三个程序

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


int main ()
{
    
    int i=0;
    char arr1[5][10]={"ball","wall","window","table","tv"};
    printf("\n");
    char *d;
    d=&arr1[0][0];
    char **dd;
    dd=&d;
    for(dd=&d ; *dd ; dd++)
    {
        printf("\nthe words are %s",*dd); 
         
    }
    
    
    return 0;
}

【问题讨论】:

  • 您的文字询问d++,但这不在您的代码中...!?
  • @4386427 对不起,我现在编辑了

标签: c pointers multidimensional-array implicit-conversion pointer-arithmetic


【解决方案1】:

dd 首先指向d。 **valueofdis the address ofarr1so when you dereferencedd`,你得到一个指向数组开头的指针,你可以使用该指针打印单词“ball”。没关系。

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

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

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

【讨论】:

  • @4386427我明白你说的我没注意到我拿了2倍的dd++现在我澄清一下
【解决方案2】:

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

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

同时存储在指针dd中的值没有被改变指针dd仍然指向指针d

在第二个程序中,指针dd 由指针d 的地址初始化。但是在递增指针 dd 后会指向指针d 之后的内存。因此,for 循环具有未定义的行为。

d=&arr1[0][0];
char **dd;
dd=&d;
for(dd=&d ; *dd ; dd++)
                  ^^^^
{
    printf("\nthe words are %s",*dd); 
    d++; 
}

循环中的这条语句

    d++; 

不影响指针dd,因为在增加指针dd之后,它还没有指向指针d

第三个程序也存在同样的问题。那是在for循环中增加指针dd之后

for(dd=&d ; *dd ; dd++)

它指向指针 d 之外的内存,并且使用表达式 *dd 调用未定义的行为。

您可以使用以下方法,使用指针来输出存储在二维字符数组中的字符串。

#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

这是在表达式中使用的数组指示符,很少有例外被转换为指向其第一个元素的指针。

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

puts( *d );

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

【讨论】:

  • 我明白你的意思,但我注意到你使用const size_t 而不是size_t 你为什么这样做?
  • @Βill97 由于数组 arr1 具有固定大小,因此很自然地将变量 M 声明为常量变量,因为数组的大小不会在程序中更改。
猜你喜欢
  • 2013-04-20
  • 2011-03-21
  • 1970-01-01
  • 2020-08-13
  • 2020-04-26
  • 2021-03-02
  • 2011-02-06
  • 2012-11-24
  • 1970-01-01
相关资源
最近更新 更多