在我的课堂笔记中对字符串指针迭代感到困惑

时间:2014-03-16 07:36:58

标签: c

这是我从讲义中复制的代码块

/* 2D processing */
printf("\n");
for (i=0; i<3; i++)
    for (j=0; j<3; j++)
        printf("%d ", *(*(ar+i)+j) );

由于ar是指向地址位置的指针,*(ar+i)实际上是指ar+i地址位置的内容,但我不明白它是如何工作的*(ar+i)+j,就像内容+数字一样。

还有一件事,

(1) char *ptr; ptr = "This is a string";
(2) char *ptr = "This is a string";

当声明和作业分开时,为什么(1)不能是char *ptr; *ptr="this a string"

非常感谢你。

4 个答案:

答案 0 :(得分:5)

在第一种情况下,ar很可能是指向指针的指针(声明为int **ar;),因此*(a + i)指针< / strong>或数组,*(*(a + i) + j)是元素。

在C和C ++中,有一条规则说数组在很多情况下可以隐式“衰减”到指向第一个元素的指针,因此也可能以其他方式声明ar

int **ar;     // (1) A pointer to a pointer
int *ar[3];   // (2) An array of pointers
int ar[3][3]; // (3) An array of arrays

ar + i写入ar是一个数组时,它会衰减到指向第一个元素的指针(情况2和3),结果是指针的地址(情况2)或者数组的地址(3)。使用解除引用运算符*然后获取指针或数组元素。

当你添加j并且元素是一个数组(情况3)时,这个数组在计算加法之前也会衰减到指向它的第一个元素的指针。因此,回顾一下,取决于ar的定义方式:

ar                // (1) a pointer to a pointer,
                  // (2) a pointer to array,
                  // (3) an array of array

ar + i            // (1) and (2) address of a pointer
                  // (3) address of array

*(ar + i)         // (1) and (2) a pointer
                  // (3) an array

*(ar + i) + j     // address of an integer in any case

*(*(ar + i) + j)  // an integer in any case

如果这看起来令人困惑,请不要担心,因为它是。通常,当您使用*(x + i)时,因为x是一个指针,这就是我猜测ar已被声明为int **ar;的原因。另请注意,在C和C ++中*(x + i)完全等同于x[i]或甚至i[x]

在第二种情况下,原因是声明是如何用C语言编写的。

char * s = "foo";

应该被理解为

(char *s) = ("foo");  // Not legal C, just to show type declaration and
                      // initialization

换句话说,*s的类型声明的一部分,而不是应用于s的操作。

但请注意

char *s, t;

s声明为char *,将t声明为char

类型声明可能是C语法中最强大但最困难的部分,因为声明的部分并不明显。例如

int *(*f)(int *(*g)(int x));

f类型的有效声明,而名称gx则无关紧要,可以省略。

int *(*f)(int *(*)(int));  // Same as above

在这种情况下,f的类型是一个指向函数的指针,该函数接受指向接受int的函数的指针并返回指向int的指针,并返回指向int的指针。

我的猜测是,绝大多数C程序员在解读之前需要先考虑一下:-D

答案 1 :(得分:2)

详细说明一下:

  • a[b]始终是*(a+b)
  • 的简写

如果将它与指针算术规则组合(或从那里派生出来),ab中的任何一个都可以是指针,另一个是整数,表示偏移。

使用此规则,您可以将*(*(ar + i) + j)等表达式转换为*(ar[i] + j),然后转换为ar[i][j]

唉,你不能告诉我们ar是什么,但我们可以告诉你:

  • 由于ar[i][j]是一个有效的表达式,ar[i]是一个指针或数组,它已经衰减到此表达式中的指针。
  • ar
  • 的计数相同
  • 为了使其成立,ar可以是

    中的任何一个
    • type** ar
    • type (*ar)[]
    • type ar[][]
    • type * ar[]

    其中type是每个组件的类型。

    这四种选择都有不同的内存布局,但访问方式相同。

指针算术和数组衰减是如何工作的。最好看一本好书或教程。

第二个问题最好是一个单独的问题。

这只是因为C的分配和初始化规则。

您定义指针

  • 未初始化:type * p;
  • 或已初始化:type * p = <init value>;

p = <new value>;

是你如何分配它。

请记住,字符串文字会在其只读内存部分转换为该字符串的地址。

答案 2 :(得分:1)

问题1)*(*(ar+i)+j)=ar[i][j]; 这是因为,ar是完整2D阵列的基地址。 并且ar[i](或*(ar+i)i从0到no_of_rows-1将包含数组中每行的地址。 然后ar[i][j](或*(*(ar+i)+j)为您提供特定地址的值。

您还应该查看2D(也是3D)数组的内存表示,以获得更多清除。

问题2):

当您说ptr="abc";字符串"abc"的地址存储到ptr时。

答案 3 :(得分:1)

我认为ar是指向指针的指针。

int **ar;   

ar指的是指向ar的指针的地址,即指向int指针的指针。
*ar指的是地址ar指向的内容,即指向int的指针。
*(*ar)指的是指针指向的地址的内容(ar点),即int

  

为什么(1)不能成为char * ptr; * ptr =&#34;这是一个字符串&#34;当声明和作业分开时?

请注意,*在声明中使用时不是间接运算符。它仅在语句中用作一元运算符时才执行间接。