【问题标题】:Why does my strCopy implementation work?为什么我的 strCopy 实现有效?
【发布时间】:2016-10-18 10:26:12
【问题描述】:

这里是strCopy的一个实现

void strcopy2(char *dst, char const *src){
    while ((*dst++ = *src++))
        ;
}

我们的教授要求我们在不使用指针的情况下重现这段代码,所以我想出了以下函数:

void strcopy(char dst[], char const src[]){
    size_t i = 0;
    while (dst[i] = src[i++])
        ;
}

它运行良好,但我意识到,在底层函数必须仍然使用指针,因为我们无处返回任何值。换句话说,我虽然最后一个函数会使用按值传递,但显然不是这样。那么在水下发生了什么,这两种方法实际上有什么区别吗?

【问题讨论】:

  • 这里有一些关于为什么指针和数组不是一回事的背景知识cplusplus.com/forum/articles/9
  • 此代码 `while (dst[i] = src[i++]) ;` 具有未定义的行为:i 的两个增量,没有中间序列点。将其更改为 `while (dst[i] = src[i]) i++;`.

标签: c++


【解决方案1】:

不只是在幕后……dstsrc,尽管看起来,实际上 指针!参数列表中的[] 语法是语法糖(或实际上是语法辣椒),但它在骗你;这些是char* dstchar const* src 实数。

8.3.5/5 [dcl.fct] 功能:

确定每个参数的类型后,将任何类型为“T数组”或函数类型T的参数调整为“指向T的指针”。

【讨论】:

  • @Trevir 在这种情况下它们是相同的。
  • @UKMonkey 请查看@Lightness 的评论。声称不是“数组是指针”,因为它们不是。声明是“dstsrc 是指针”,它们是。我添加了标准报价。
  • 不,@Trevir。这是不正确的。 OP 的两个函数(略微)不同,但与它们的参数无关。
  • 为免生疑问,大家,这是一个 C++ 怪癖(实际上是一个 C 怪癖),如果你写 void foo(int array[]) 这是字面意思翻译成在各方面相同void foo(int* array)。是的,这很愚蠢和令人困惑。感谢帕特里克在这个答案中添加了相关的标准。
  • @Trevir:我从未声称这两个 [功能] 是相同的。我现在实际上已经说过两次相反的说法了。
【解决方案2】:

这两种方法实际上有什么区别吗?

是的,第二个就是错的:

void strcopy(char dst[], char const src[]){
    size_t i = 0;
    while (dst[i] = src[i++]) // (*)
        ;
}

标记为(*) 的行在C++ 的大部分历史中是未定义的行为。关于增量,i 的两次读取没有指定的顺序。这可能会在您平台上的编译器上正确排序。 i 的增量可能会在它被读取为dst 的索引之前发生,并且您的复制功能将关闭一。在 C++17 中,将首先评估右侧,因此复制函数将肯定减一。

你会想要让增量成为它自己的表达式:

void strcopy(char dst[], char const src[]){
    size_t i = 0;
    while (dst[i] = src[i]) {
        ++i;
    }
}

【讨论】:

  • @KonradRudolph 是的,这是真的,并且已经被 Lightness 覆盖。我只是回答问题的另一部分。
  • 感谢您的回答! Tbh,我有点摆弄++,直到副本按预期工作。值得注意的是,这确实是未定义的行为!
【解决方案3】:

这是腐烂的过程

对于编译器,数组的name 成为第一个元素的指针。

请注意数组和指针并不相同。它是 namesymbol 被视为指向数组第一个元素的指针。

所以在您的示例中,char dest[] 被编译器视为&dest[0],或者换句话说,char* dest

根据语言规则,如果p是一个指针,那么p[x]被视为*(p+x),这就是为什么两个例子中生成的机器码几乎相同。

【讨论】:

  • 衰败是故事的 1/2。另一个答案中解释了更重要的一半。事实上,OP 的代码并没有发生太多的衰减(除了间接通过例如dst[i]。)
猜你喜欢
  • 2018-07-13
  • 2011-01-11
  • 2019-07-13
  • 2010-10-17
  • 2013-12-17
  • 1970-01-01
  • 1970-01-01
  • 2019-12-04
  • 1970-01-01
相关资源
最近更新 更多