C 是++;与+;相同1个指针?

C 是++;与+;相同1个指针?,c,pointers,post-increment,C,Pointers,Post Increment,我想重构我的一些旧C代码,我很好奇是否可以用ptr+=1替换所有ptr++,其中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++时,我得到了相同的结果,但我想知道是否所有类型

我想重构我的一些旧C代码,我很好奇是否可以用
ptr+=1
替换所有
ptr++
,其中
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++
时,我得到了相同的结果,但我想知道是否所有类型都是这样。我还对
int
s进行了测试:

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 a = 5;
int b = a;
a += 1;
结论

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


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

a++=1
相当于
++a
(C99§6.5.3.1/2)。在像
intb=a++
这意味着它不等同于
a++
a++
将返回
a
的旧值,而
a+=1
将返回新值

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

另外,请注意,所有指针运算都是以指向类型大小的增量进行的(§6.5.6/8)。这意味着:

ptr = ptr + x;
相当于:

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

无论您使用
+
+
+=
还是
[]
p[x]
完全等同于
*(p+x)
;您甚至可以这样做
4[“Hello”]

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

这是一个好问题。答案是肯定的,你可以做到这一点——不管你怎么做,递增指针都会给指针增加
sizeof(指针指向的类型)
。正如其他答案所示,您确实需要小心,不要依赖于增量发生的时间,即a++和++a具有不同的效果,但a最终会得到相同的值


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

为什么
a++=1
不是对
a++
的改进。如何进行重构?@CanSpice因为在很多情况下,向指针添加
x
实际上会在所有情况下添加
x*sizeof(*ptr)
@Toomai。@meagar我使用广义的重构这个术语,还包括代码格式清理、变量名澄清和更改目录结构等。我相信
a++=1
a++
有改进,因为它有一种微妙的味道。我认为它跨越了简洁和简洁之间的界限。你确定它等同于转换为
char*
而不调用UB吗?另外,我讨厌迂腐,但我非常确定
*(p+x)
应该是
*(p+(x))
@Pubby,参见C99§6.2.5/20、§6.2.6.1/4、§6.3.2.3/7。C要求数组是连续分配的,并且它们的组成对象的大小固定为字符位的倍数。我们通过与C所要求的算法等价的算法,得到一个指向数组元素的字符指针;因此
(char*)p+sizeof(*p)*x==(char*)和p[x]
。此外,6.3.2.3/7要求我们可以将指针转换回对象类型(因为它已正确对齐),从而返回到
&p[x]
。虽然没有直接说明,但实施上的限制实际上需要这样做。谢谢您的参考!有道理。哇,很好,谢谢。我没想过要真正审视语言标准。我想这主要是一种风格。另外,Crockford说他不允许他的人在JavaScript中使用它。我在工作中使用C、Java和VB.NET,在家中使用JavaScript、Ruby和其他语言,所以我希望在不同语言之间保持一致。我理解编写惯用代码的重要性,但我觉得++和-,代表了一种我在任何语言的代码中都不想要的聪明或C语言。
ptr = (ptr_type *)( (char *)ptr + x * sizeof(*ptr) );