【问题标题】:Changing to Pointer Arithmetic更改为指针算术
【发布时间】:2016-02-21 03:40:01
【问题描述】:

我是 C 中指针的新手,在弄清楚如何使用它们时遇到了很多麻烦。

我在 void 函数中有一段带有指针算法的代码:

void function(int n, int *a, int *b){
   int *p,*q;
   q = b;
   int i;
   *b = 0;

    for (i = 1; i<n; i++)
       if(*(a+i) == *(a+i-1))
          *(b+i)=0;
       else
          *(b+i)=1;
}

我正在尝试将其完全更改为仅使用没有循环索引变量的指针算术。到目前为止,我已经得到了这个:

void function(int n, int *a, int *b){
   int *p,*q;
   q = b;
   *b = 0;

    for (p = a+1; p<a+n; p++)
       if(*a == *a-1)
          *b=0;
       else
          *b=1;
}

但据我了解,它与上面的第一段代码不完全相同吗?我错过了什么吗?感谢您的帮助

【问题讨论】:

  • for (p = a+1; p&lt;a+n; p++) *++b = (*p != *(p-1));
  • 谢谢蓝色小精灵!对此,我真的非常感激。这些指针好复杂
  • @Ashley - 指针并不复杂 - 你每天都在使用它们。在路上,一个标有left to X 的标志的值是left to X - 它指向的是x,在这种情况下是整数。指针本身会告诉你 X 在哪里

标签: c pointers pointer-arithmetic


【解决方案1】:

如果您对 pointer 有一点苦恼,那么如何理解 pointer 的简短版本就是理解它只是一个包含 地址的变量 到别的东西作为它的。取一个普通变量int x = 5;,其中x 包含立即值 5

另一方面,指针不包含立即值,但包含可以找到立即值(或其他指针)的地址在记忆中。这为您如何使用指针提供了相当多的灵活性。正如您可以在x(例如x++;)上使用算术来递增5 -> 6,当您将一个指针 递增到一个数组时,指针现在指向下一个数组中的地址。

因此,如果您声明了int a[] = {3, 5, 7, 9};,那么在分配为a 的存储的顺序内存块中,您将有以下关于a 的关系:

 a    m1  m2  m3  m4    /* points to memory locations m1 -> m4 */
    | 0 | 1 | 2 | 3 |   /* the zero based array indexes        */
    | 3 | 5 | 7 | 9 |   /* the values stored in m1 -> m4       */

您希望消除使用数组索引0-4 并仅使用内存地址位置信息及其值在function 中执行相同的操作。这就是 pointer-arithmetic 可以像数组索引一样用于设置、比较、删除数组中的值的地方。当使用指针迭代数组时,您通常会声明一个用于迭代目的的指针这样您就不会丢失您的内存块的起始地址

谢天谢地,当指针(或转换后的数组)作为参数传递给函数时,函数接收到 pointer副本,而不是原始地址调用函数中的指针。您可能仍然需要保存一个指针来保存 copy 的原始地址,但这仅取决于您需要在 function 中做什么。

如果您想在function 中重新实现相同的逻辑,增加指针而不是增加索引'i',那么您将需要处理ab 中第一个指针位置的增量当您设置默认 *b=0; 时。虽然您可以通过迭代for (i = 1;... 来简单地跳过每个使用索引中的第一个字符,但如果您采用这种方法,则必须自己增加指针。您可以通过简单地跳过 a 保存其原始地址的迭代在循环内处理它:

void functionp (int n, int *a, int *b)
{
int *p = a;  /* saved the original value of the copy */
*b = 0;

    for (; a < p + n; a++, b++)
        if (a > p)
            *b = (*a == *(a - 1)) ? 0 : 1;
        else
            continue;  /* skip first loop where 'p == a' */
}

或者,您可以在开始循环之前同时增加ab(例如a++, b++;),以确保您在if 语句中处理a 中的第二个和第一个字符。一个例子是:

void functionp (int n, int *a, int *b)
{
int *p = a;  /* saved the original value of the copy */
*b = 0;

    a++, b++;  /* increment both 'a' and 'b' */
    for (; a < p + n; a++, b++)
        *b = (*a == *(a - 1)) ? 0 : 1;
}

由于您似乎对指针的取消引用方面有一个公平的处理,以便对内存中指向的值进行操作,我将把它留给您。一个简短的比较示例允许您运行不带参数的代码(或不以 'f' 开头的参数)以查看数组上原始函数的结果,或者提供以 'f' 开头的参数将调用指针使用功能:

#include <stdio.h>

void function (int n, int *a, int *b);
void functionp (int n, int *a, int *b);

int main (int argc, char **argv) {

    int a[] = {1,1,2,2,3,3,3,4};
    int i, n = sizeof a/sizeof *a;
    int b[n];

    if (argc > 1 && *argv[1] == 'f') {
        printf ("\n executing 'function'\n\n");
        function (n, a, b);
    }
    else {
        printf ("\n executing 'functionp'\n\n");
        functionp (n, a, b);
    }
    for (i = 0; i < n; i++)
        printf (" a[%d] : %d | b[%d] : %d\n", 
                i, a[i], i, b[i]);

    return 0;
}

void function (int n, int *a, int *b)  /* original function */
{
int i;
*b = 0;

    for (i = 1; i < n; i++)
    if(*(a+i) == *(a+i-1))
        *(b+i)=0;
    else
        *(b+i)=1;
}

void functionp (int n, int *a, int *b) /* pointer use only function */
{
int *p = a;
*b = 0;

    a++, b++;  /* increment both 'a' and 'b' */
    for (; a < p + n; a++, b++)
        *b = (*a == *(a - 1)) ? 0 : 1;
}

使用/输出示例

$ ./bin/idx2ptr f

 executing 'function'

 a[0] : 1 | b[0] : 0
 a[1] : 1 | b[1] : 0
 a[2] : 2 | b[2] : 1
 a[3] : 2 | b[3] : 0
 a[4] : 3 | b[4] : 1
 a[5] : 3 | b[5] : 0
 a[6] : 3 | b[6] : 0
 a[7] : 4 | b[7] : 1


$ ./bin/idx2ptr p

 executing 'functionp'

 a[0] : 1 | b[0] : 0
 a[1] : 1 | b[1] : 0
 a[2] : 2 | b[2] : 1
 a[3] : 2 | b[3] : 0
 a[4] : 3 | b[4] : 1
 a[5] : 3 | b[5] : 0
 a[6] : 3 | b[6] : 0
 a[7] : 4 | b[7] : 1

查看函数和示例,如果您有任何问题,请告诉我。我希望这会有所帮助。

【讨论】:

    【解决方案2】:

    您的程序有一些未使用的变量。不要忽视编译器的警告。

    我猜你的意思是:

    void function0(int n, int *a, int *b)
    {
        b[0] = 0;
        int i;
        for (i = 1; i < n; i++)
            if(a[i] == a[i-1])
                b[i] = 0;
            else
                b[i] = 1;
    }
    

    function0()在语法上

    相同
    void function1(int n, int *a, int *b)
    {
        *b = 0;
        int i;
        for (i = 1; i < n; i++)
            if(*(a + i) == *(a + i - 1))
                *(b + i) = 0;
            else
                *(b + i) = 1;
    }
    

    功能等同于:

    void function2(int n, int *a, int *b)
    {
        *b = 0;
        int *p, *q;
        for (p = a + 1, q = b; p < a + n; p++, q++)
            if(*p == *(p - 1))
                *q = 0;
            else
                *q = 1;
    }
    

    【讨论】:

      【解决方案3】:

      它们不一样,你必须在for正文中将a替换为p,并使用q指针修改b

      void function(int n, int *a, int *b)
      {
         *b = 0;
          for (int *p = a + 1, *q = b ; p < a + n ; ++p, ++q)
          {
             if (*p == *(p - 1))
                *q = 0;
             else
                *q = 1;
          }
      }
      

      【讨论】:

      • 想知道同样的事情...... i 不应该在那里?
      • @Ashley 和 Bluepixy!对!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 2010-09-28
      • 2012-07-27
      • 1970-01-01
      相关资源
      最近更新 更多