2012-06-18 29 views
7

我的印象是后增量(OR预增量)只能在右侧(=)的右侧完成。但我可以编译下面的一段代码。 你能帮我理解这个特定的代码,特别是在下面的行。 来源:http://www.ibm.com/developerworks/library/pa-dalign/后增加在左侧

*data8++ = -*data8; 


void Munge8(void *data, uint32_t size) { 
    uint8_t *data8 = (uint8_t*) data; 
    uint8_t *data8End = data8 + size; 

    while(data8 != data8End) { 
     *data8++ = -*data8; 
    } 
} 
+0

分配' - * data8'到'* data8'然后增加'data8' - 有效地抵消了'size'在'data' – Erik

回答

3

你的印象是错误的,我猜。你绝对可以做这样的事情:

*a++ = *b++; 

事实上,这通常是如何实现strcpy。你甚至可以有后或预增量没有=可言:

a++; 
+0

等待字节,所以我同意与您的原始帖子。这不是什么不确定的行为? –

+0

strcpy没有像那样实现。您首先以大块数据的位模式查找字符串的结尾,然后以较大的块(通常为64位)复制数据。 – 2012-06-18 18:31:40

+0

@sharth:虽然它没有定义?我不是一个标准的瘾君子,但是必须先评估RHS,然后再评估LHS。因此应该没有问题。 – 2012-06-18 18:33:07

1

有没有理由后递增不能赋值运算符的左侧进行。后增加运算符只是返回对象在其先前状态下的临时副本,并且该临时对象(在本例中为指针)可以对其执行操作。

现在,在的情况下:

*data8++ = -*data8; 
因为运营商订购的

,该data8指针将首先进行递增,返回先前的指针值的副本。之前的指针值将被取消引用,并在赋值运算符的右侧分配表达式的结果。

编辑:正如其他人所指出的那样,你是通过读不止一次在写入没有序列点存储位置更多修改的data8内容,所以这是不确定的行为。

+0

这是怎么定义的?这就像声称'x = -x'是未定义的。 –

+0

您正在修改'data8'的内容(即指针值本身),然后在没有序列点的情况下将它读回两个不同的位置。正如其他人所指出的那样,如果首先评估LHS或RHS,您将得到两个不同的结果...因此“未定义的行为”,因为C标准没有定义首先必须评估哪一方......例如, LHS和RHS的评估可以交错使用!在你的例子中,有一个明确的评估顺序,因为LHS没有读取'x'的值,它只是写给它。所以只有一个读/写。 – Jason

+0

是的。我会声称缺乏睡眠作为借口。 –

2

++应用于指针,而不是data8指向的值。

*data8++ = -*data8;

等同于:

*data8 = -*data8; 
data8++; 

编辑:
阅读C99 standard 6.5Annex C后,很明显=不是一个序列点。标准仅提到&&||,,?

因为,data8上的=两面没有顺序点和标准不强制RHS是否应首先评估或LHS应先评估修改,我相信这是未定义行为。

Any good reason why assignment operator isn't a sequence point?

这上面的帖子讨论=是不是一个序列点,这里是非常相关的。

+0

'data8'在赋值操作符的两侧都没有被修改,而是在LHS中被修改,但它被读取了两次,没有序列点确定读取是如何针对写入进行排序的。 – Jason

+0

@Jason你是对的。 '='不是顺序点是这里的关键。 –

7

所以,我很确定这是未定义的行为。没有比在最后一个分号其他没有顺序点:

*data8++ = -*data8; 

如果DATA8等于为0x20,这是等于:

*(0x20) = -*(0x20); 

*(0x20) = -*(0x24); 

因为没有做出这一决定的方式,(因为您在读取两次的同时编辑了一个变量,没有交错序列点),这是未定义的行为


虽然我们可以谈论下面的代码片段是做什么的。这可能是上述代码的意图。

while(data8 != data8End) { 
    *data8 = -*data8; 
    data8++; 
} 

你在这里做的是希望更直接的。你正在把你的输入数组,看着它,所以它是一系列的8位数字。然后,就地,你否定每一个。

+0

我认为你在这里混淆了“变量”。由地址指针存储的指针值和值是两个不同的东西。在这种情况下,没有人在读两次的同时编辑了一个变量。地址指针处的“data8”值在RHS上读取一次。它被写回一次。指针在LHS上更改一次。 – 2012-06-18 18:45:16

+0

或者我可以。 Hehe – 2012-06-18 18:48:25

+2

@Vlad,'='不是序列点。 –

0

我认为

* DATA8 ++ = - * DATA8;

相当于

* DATA8 = - *(DATA8 + 1);

DATA8 = DATA8 +1