【问题标题】:Is ++ the same as += 1 for pointers?++ 是否与指针的 += 1 相同?
【发布时间】:2011-12-07 19:10:27
【问题描述】:

我想重构我的一些旧 C 代码,我很好奇是否可以将所有 ptr++ 替换为 ptr += 1 其中 ptr 是一些指针,而不改变任何行为。这是我的意思的一个例子,来自 K&R 第 5.3 节:

/* strlen: return length of string s*/
int strlen(char *s)
{
    int n;
    for (n = 0; *s != '\0'; s++)
        n++;
    return n;
}

当我用s += 1 替换s++ 时,我得到了相同的结果,但我想知道这是否适用于所有类型。我还对ints 做了一个测试:

int size = 10;
int *int_array = (int*)calloc(size, sizeof(int));
for (int i = 0; i < size; i++)
    int_array[i] = i;

for (int i = 0; i < size; i++) {
    printf("*int_array = %d\n", i, *int_array);
    int_array++;
}

如果我将行 int_array++; 替换为 int_array += 1;,我会得到相同的结果。

再想一想之后,我意识到如果在表达式中使用该值可能会出现问题。我只是将增量移动到另一行这样会更安全吗:

int a = 5;
int b = a++;

会变成:

int a = 5;
int b = a;
a += 1;

结论

我认为可能是一个问题,增加不同类型的指针,这不是问题。原因见@bdonlan 的回复。

这并不意味着您可以将所有 x++ 替换为 x += 1 并期望相同的行为。但是,您可以安全地将++x 替换为(x += 1),因为它们是等效的。

【问题讨论】:

  • 为什么? a += 1 不是对 a++ 的改进。这是如何重构的?
  • @CanSpice 因为在很多情况下,将x 添加到指针实际上会添加x*sizeof(*ptr)
  • @Toomai,实际上在所有情况下。
  • @meagar 我在广义上使用术语重构,它还包括代码格式清理、变量名澄清和更改目录结构等。我相信a += 1 是对a++ 的改进,因为它有一种棘手的味道。我认为它只是跨越了简洁和简洁之间的界限。

标签: c pointers post-increment


【解决方案1】:

a += 1 等同于++a(C99 §6.5.3.1/2)。在像int b = a++; 这样的行中,这意味着它 等同于a++a++ 将返回a值,而a += 1 返回新值。

请注意,如果您不使用 a++ 的结果(即,您有一个仅包含 a++; 的语句),那么它们实际上是相同的。

另外,请注意 _all 指针运算是以指向类型的大小为增量完成的(第 6.5.6/8 节)。这意味着:

ptr = ptr + x;

相当于:

ptr = (ptr_type *)( (char *)ptr + x * sizeof(*ptr) );

无论您使用++++= 还是[],这都是相同的(p[x] 完全等同于*(p + x);因此您甚至可以执行4["Hello"] 之类的操作)。

【讨论】:

  • 你确定它相当于投射到char*而不是调用UB吗?另外,我讨厌迂腐,但很确定*(p + x) 应该是*(p + (x))
  • @Pubby,参见 C99 §6.2.5/20、§6.2.6.1/4、§6.3.2.3/7。 C 要求数组是连续分配的,并且它们的组成对象具有 CHAR_BIT 位的某个倍数的固定大小。我们通过算术得到一个指向数组元素的字符指针,这相当于 C 所要求的;因此(char *)p + sizeof(*p)*x == (char *)&amp;p[x]。进一步的 6.3.2.3/7 要求我们可以将指针转换回对象类型(因为它已正确对齐),因此我们回到&amp;p[x]。它没有直接说明,但对实施的限制有效地要求这样做,IOW。
  • 感谢您的参考!有道理。
  • 哇,非常好,谢谢。我没想到真正看语言标准。
【解决方案2】:

++-- 是根据内置类型的算术定义的。行为将是相同的,除了后缀返回旧值。

【讨论】:

    【解决方案3】:

    这是个好问题。答案是肯定的,你可以这样做——不管你怎么做,递增指针会将sizeof(the type that the pointer points to) 添加到指针中。正如其他答案所表明的那样,您确实需要注意不要依赖 when 增量发生,即 a++ 和 ++a 具有不同的效果,但 a 最终以相同的值结束。

    一个问题是:为什么您要将所有代码从a++ 更改为a+=1?任何 C 程序员都应该很容易理解将后自增运算符与指针一起使用,因此很难理解为什么要进行这种更改。

    【讨论】:

    • 我想这主要是一种风格。此外,Crockford 说他不允许他的人在 JavaScript 中使用它。我在工作中使用 C、Java 和 VB.NET,在家里使用 JavaScript、Ruby 和其他语言,所以我希望在不同语言之间保持一致。我理解编写惯用代码的重要性,但我觉得 ++ 和 -- 代表了一种我不希望在任何语言的代码中出现的聪明或仅 C 语言。
    猜你喜欢
    • 2021-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多