C 是++;与+;相同1个指针?
我想重构我的一些旧C代码,我很好奇是否可以用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++时,我得到了相同的结果,但我想知道是否所有类型
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) );