-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 中?
指针是存储地址的变量。该地址可以是另一个变量的地址:
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之后,
arg和targ都会递增以前进到序列中的下一个元素。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将具有新值。