学习c 无法理解指针

-5 c

void
bar (char *arg, char *targ, int len)
{
  int i;
  for (i = 0; i < len; i++)
  {
    *targ++ = *arg++;
  }
}
Run Code Online (Sandbox Code Playgroud)

现在正在学习c,一个朋友给我发了这个片段,我不明白它的作用。对指针部分的解释会很有帮助。根据我的理解,它似乎是将 arg 的值复制到 i 字符的 targ 中?

Pab*_*blo 5

指针是存储地址的变量。该地址可以是另一个变量的地址:

int a = 18;
int *pa = &a;
Run Code Online (Sandbox Code Playgroud)

或者它可以是动态分配的内存块的开始:

int *p = malloc(sizeof *p);
Run Code Online (Sandbox Code Playgroud)

重要的是指针允许您访问地址后面的值。您可以通过使用 - 运算符取消引用指针来做到这一点*

int a = 18;
int *pa = &a;

*pa = 10;

printf("a=%d\n", a); // will print 10
Run Code Online (Sandbox Code Playgroud)

对于这些类型的示例,这可能看起来没什么大不了的,但事实确实如此,因为您可以将指针传递给函数,然后这些函数可以根据内存块与指针指向的内存进行交互,甚至可以修改它。

指针还可以指向对象序列的开头,例如数组的开头:

int arr[] = { 1, 3, 5 };
int *p = arr;
Run Code Online (Sandbox Code Playgroud)

注意p[0]is 1、p[1]is 3 和p[2]is 5。也可以通过执行 来更改值p[1] = -14;。这也是解除引用,但您也可以使用 *- 运算符:

p[1] = 12;
// is equivalent to
*(p + 1) = 12;
Run Code Online (Sandbox Code Playgroud)

这就是您的代码片段所使用的。暂时忘记循环。看看这一行:

*targ++ = *arg++;
Run Code Online (Sandbox Code Playgroud)

这可以重写为:

targ[0] = arg[0];
targ = targ + 1;  // or targ = &(targ[1])
arg = arg + 1;    // or arg = &(arg[1])
Run Code Online (Sandbox Code Playgroud)

现在更清楚它在做什么了。它将 指向的第一个字符的值复制到指向的arg位置。targ之后, argtarg都会递增以前进到序列中的下一个元素。1

所以循环所做的就是复制to len指向的对象。这可用于将字符串复制到另一个数组中。但它并不安全,因为不清楚终止字节是否被复制,也不清楚缓冲区是否足够大(意味着大于 )。如果它们不是字符串而是字节序列,那么这个函数就可以了。argtargchar'\0'len

在 C 中,字符串只是以'\0'- 终止字节结尾的字符序列。因此,它们使用char数组存储,并作为 的指针传递给函数char,该指针指向字符串的开头。我们可以用更安全的方式重写这个函数,如下所示:

int safe_copy_string(char *dest, char *source, size_t dest_size)
{
    if(dest == NULL || source == NULL)
        return 0;

    if(dest_size == 0)
        return 1; // no space to copy anything

    // copying one element less than dest_size
    // that last element if dest should be \0
    for(size_t i = 0; i < dest_size - 1; ++i)
    {
        *dest++ = *source++;

        if(*(source - 1) == '\0')
            break; // copied sources's 0-terminating byte
    }

    dest[dest_size - 1] = 0; // making sure it is 0-terminated

    return 1;
}
Run Code Online (Sandbox Code Playgroud)

脚注

1这里值得一提的是++- 运算符。这是后递增运算符,用于将操作数加 1(对于整数),如果是指针,则将指针前进 1,从而使其指向下一个对象。

当你这样做时:

int a = 6;
int b = a++;
// a == 7, b == 6
Run Code Online (Sandbox Code Playgroud)

a初始化为 6。初始化 时b,编译器将使用 的当前值a进行初始化,但是后自增运算符有副作用,它会将 的值增加a1。何时发生这种情况由以下规则定义序列点。重要的是,在 的初始化中b,使用 的当前值a,并且在赋值之后a将具有新值。