我有一个指向数组元素的指针,该数组元素在函数中用作参数,并通过"++"操作在所述函数内沿着数组移动.我希望在函数完成后重新使用指针的更新位置.

下面的代码包含两个解决问题的try .第一次try —通过move_pointer功能—是在answer to a similar question上扩展.不幸的是,它似乎不起作用,函数参数似乎不受影响. 第二次try —via move_pointer_func函数—按预期工作,但我看不出有什么方法可以扩展到同 timeshift 动两个这样的指针的情况.因此,我将感谢任何关于如何实现与修改move_pointer功能而不是的建议.

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void move_pointer(const double** pointer){
    *pointer++;
}

const double* move_pointer_func(const double* pointer){
    pointer++;
    return pointer;
}

void check_pointer_movement(const double* input_vec, const int ndim, const bool use_func) {
    const double* input_vec_pointer=&input_vec[0];
    for (int i = 0; i!=ndim; i++){
        printf("%e\n", *input_vec_pointer);
        if (use_func){
            input_vec_pointer=move_pointer_func(input_vec_pointer);
        }
        else {
            move_pointer(&input_vec_pointer);
        }
    }
}

int main() {
   int ndim=4;
   double input_vec[4]={0.25, 0.65, 0.95, 1.2};
   printf("First attempt:\n");
   check_pointer_movement(input_vec, ndim, false);
   printf("Second attempt:\n");
   check_pointer_movement(input_vec, ndim, true);
   return 0;
}

推荐答案

但我看不出有什么方法可以扩展解决方案, 移动两个这样的指针的情况, 一次

        The 2 are equivalent and neither one
            changes 2 pointers at once.

The problem in move_pointer()

    void move_pointer(const double** pointer){*pointer++;}

考虑这个图像,代码和输出并排(源代码在下面)

enter image description here

这只是操作符和地址变化的可视化.32-使用位平台,仅用于较短的地址

从代码

    p = *ppInt++; // a
    printf("\
        [1] *p is %d\n\
        ppInt now points to 0x%p\n", *p, ppInt);
  • 这里*ppInt被分配给p
  • 则增加ppInt

这样,p指向a[],所以*pa[0],也就是17.但是ppInt是递增的,下一个命令显示首先运行的是什么:++

    p = *ppInt; // b
    printf("    [2] *p is %d\n", *p);

它会打印出

    [2] *p is 420

因此,将ppInt递增为指向b[0]

而现在

    p = ++*ppInt; // c
    printf("    [3] *p is %d\n", *p);

fingerprint

    [3] *p is 170

因为ppInt被取消引用before并且该值在被分配给p之前递增,所以现在指向b[1]

_

back to the original move_pointer()###

  • pointer递增
  • pointer被取消引用
  • 该函数结束,因此不会使用此值,*pointer也不会更改

++需要运行at the address pointed by 101,所以 我们需要写下 ++*pointer(*pointer)++:

  • *pointer被判断,我们仍然得到double*,因为pointerdouble**.
  • 但是现在该地址处的值随后递增.这个值是来自调用者的double**,所以调用者中的指针会被更新.

See this table from cpp reference enter image description here

例如

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

void move_pointer(const double** pointer) { ++*pointer; }

const double* move_pointer_func(const double*);

void          check_pointer_movement(
             const double* input_vec, const int ndim);

int main(void)
{
    double input_vec[] = {0.25, 0.65, 0.95, 1.2, 42., 17.};
    int    size        = sizeof(input_vec) / sizeof(input_vec[0]);

    int  a[]    = { 17,  42};
    int  b[]    = {420, 170};
    int* p      = NULL;
    int* pInt[] = {(int*)&a, (int*) & b};
    printf("\
    a[] is at 0x%p\n\
    b[] is at 0x%p\n\
    pInt address is 0x%p\n\
      pInt[0] is 0x%p\n\
      pInt[1] is 0x%p\n",
        &a, &b, 
        &pInt, pInt[0], pInt[1]);
    int** ppInt = (int**)&pInt;
    printf("    ppInt points to 0x%p\n", ppInt);
    p = *ppInt++; // a
    printf("\
        [1] *p is %d\n\
        ppInt now points to 0x%p\n", *p, ppInt);
    p = *ppInt; // b
    printf("    [2] *p is %d\n", *p);
    p = ++*ppInt; // c
    printf("    [3] *p is %d\n", *p);

    printf("\nFirst attempt:\n");
    check_pointer_movement(input_vec, size);

    // 2nd
    const double* fwd = move_pointer_func(input_vec);
    if ( (fwd - input_vec) == 1 )
        printf("Second attempt worked fine!\n");
    else
        printf("Second attempt failed to move pointer forward!\n");
    return 0;
}


const double * move_pointer_func(const double * pointer)
{
    return ++pointer;
}

void check_pointer_movement(
    const double* input_vec, const int ndim)
{
    const double* input_vec_pointer = &input_vec[0];
    for (int i = 0; i != ndim; i++)
    {
        printf("%.2f\n", *input_vec_pointer);
        move_pointer(&input_vec_pointer);
    }
}

输出

    a[] is at 0x00AFF9D4
    b[] is at 0x00AFF9C4
    pInt address is 0x00AFF9A8
      pInt[0] is 0x00AFF9D4
      pInt[1] is 0x00AFF9C4
    ppInt points to 0x00AFF9A8
        [1] *p is 17
        ppInt now points to 0x00AFF9AC
    [2] *p is 420
    [3] *p is 170

First attempt:
0.25
0.65
0.95
1.20
42.00
17.00
Second attempt worked fine!

注意到

move_pointer(double ** p)

void move_pointer(const double** pointer) {
    ++*pointer; }

这是因为++更新了现在取消引用的double**.

const double * move_pointer_func(const double * pointer)

const double * move_pointer_func(const double * pointer)
{
    return ++pointer;
}

往往更实用,因为它可以用来更新其他指针或相同的指针.

为了测试它,我们可以用这个表达式

    const double* fwd = move_pointer_func(input_vec);
    if ( (fwd - input_vec) == 1 )
        printf("Second attempt worked fine!\n");
    else
        printf("Second attempt failed to move pointer forward!\n");

因为它是C,我们把指针按它指向的东西的大小递增,我们就有了指针算术.

    double input_vec[] = {0.25, 0.65, 0.95, 1.2, 42., 17.};
    int    size        = sizeof(input_vec) / sizeof(input_vec[0]);

这允许随意向数组添加值,并保持size更新

C++相关问答推荐

海湾合作委员会是否保证大小匹配的访问?

我应该如何解决我自己为iOS编译的xmlsec1库的问题?转换Ctx.first在xmlSecTransformCtxPrepare()之后为空

不会停在空格或换行符上的错误

ATmega328P EEPROM未写入

将常量转换为指针会增加.数据大小增加1000字节

向上强制转换C中的数值类型总是可逆的吗?

具有交换链获取和命令缓冲区提交的同步-危险-读后写错误

致命:ThreadSaniizer:在Linux内核6.6+上运行时意外的内存映射

每个 struct 变量在C中都有自己的命名空间吗?

进程已完成,退出代码为138 Clion

用C++从外部ELF符号读取值

在函数外部使用内联ASM时无法指定操作数

是否定义了此函数的行为?

使用ld将目标文件链接到C标准库

静态初始化顺序失败是否适用于C语言?

在printf()中用%.*S格式填充长度为0的字符串是否会调用任何UB?如果是,是哪一个?

我正在使用c学习数据 struct ,在学习堆栈时,我试图将中缀转换为后缀,并编写了这段代码.代码未给出输出

在我的函数中实现va_arg的问题

将指针的地址加载到寄存器内联拇指组件中

我怎样才能用c语言正常运行这两个进程?