C 读 16 bit 大端数的一个小问题

2015-05-22 18:38:29 +08:00
 leeyiw
我的程序在 Ubuntu 上就能正常工作,最近在 CentOS 上运行就会出现莫名其妙的 Bug。如下:

原始代码:
static inline uint16_t
up_packet_read_uint16_be(up_packet_t *p)
{
return (*(p->pointer++) << 8) | *(p->pointer++);
}

函数只想读一个 16 Bit 大端数返回,在 Ubuntu 上, 能够正常工作, 在 CentOS 上,函数只读了第一个字节,并没有读第二个字节。谁能帮忙看下?非常感谢。

PS,up_packet_t 定义如下:
struct up_packet_s {
uint8_t *buffer;
uint8_t *pointer;
size_t length;
size_t capacity;
};
1323 次点击
所在节点    C
19 条回复
Septembers
2015-05-22 18:46:17 +08:00
cat /proc/cpuinfo
ShadowStar
2015-05-22 19:05:44 +08:00
未定义
choury
2015-05-22 19:20:09 +08:00
一个语句放两个++,结果是不确定的,和编译器实现有关
acros
2015-05-22 19:24:06 +08:00
这不是触发短路求值了么?

我去VS里面验证下,目前没gcc····
acros
2015-05-22 19:30:48 +08:00
木有试出来······

三楼说的应该是对的,我记得code warrior编译器对这种的处理就和vs相反的。
xylophone21
2015-05-22 19:33:00 +08:00
只读了第一个字节,并没有读第二个字节。这个怎么解释?
0x12 0x34 ==> 0x1200? 0x0034? 0x3412?

1. *(p->pointer++) << 8 溢出?
2. C规范定义中没有说|操作的左右顺序,但也没有说行为是未定义的。不过讲||时,它用了一个unlike,这种东西跟优先级差不多,虽然有规则,但没几个人记得住,用()规避的好。

6.5.12 Bitwise inclusive OR operator
Syntax
1 inclusive-OR-expression: exclusive-OR-expression
inclusive-OR-expression | exclusive-OR-expression
Constraints
2 Each of the operands shall have integer type.
Semantics
3 The usual arithmetic conversions are performed on the operands.
4 The result of the | operator is the bitwise inclusive OR of the operands (that is, each bit in the result is set if and only if at least one of the corresponding bits in the converted operands is set).


6.5.14 Logical OR operator
Syntax
1 logical-OR-expression: logical-AND-expression
logical-OR-expression || logical-AND-expression
Constraints
2 Each of the operands shall have scalar type.
Semantics
3 The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it yields 0. The result has type int.
4 Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; there is a sequence point after the evaluation of the first operand. If the first operand compares unequal to 0, the second operand is not evaluated.
xylophone21
2015-05-22 19:35:23 +08:00
@choury 这个说法并不准确

if( *p++ || *p++ )

行为是一定的
leeyiw
2015-05-22 19:45:10 +08:00
@xylophone21 我的意思是pointer只自增了1
leeyiw
2015-05-22 19:46:44 +08:00
@xylophone21 你说的是逻辑或,我说的是按位或。
leeyiw
2015-05-22 19:47:36 +08:00
@choury 行为确实感觉未定义,但是只自增了 1 感觉还是有点奇怪~
xylophone21
2015-05-22 19:48:28 +08:00
@leeyiw 这没有道理,除非你把 “|” 写成了 "||" 。
leeyiw
2015-05-22 19:56:27 +08:00
@xylophone21 写的确实如上面代码所述,所以感觉很诡异
choury
2015-05-22 20:21:11 +08:00
@xylophone21 我只是对楼主的这个语句


@leeyiw 这种情况如果想要准确知道发生了什么,只需要看汇编代码即可
zhicheng
2015-05-22 20:26:05 +08:00
教科书似的“未定义行为”。
Monad
2015-05-22 22:46:27 +08:00
§5/4.1 Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression.
另外这种东西不应该是直接(int16_t*)p->pointer然后ntohs最后p->pointer += 2么
leeyiw
2015-05-23 11:56:15 +08:00
@Monad 谢谢,这样很方便
xylophone21
2015-05-23 22:42:26 +08:00
@Monad 他的数据是bigend,而现在的cpu以littleend的居多,你确定这样可以?
xylophone21
2015-05-23 22:43:04 +08:00
@leeyiw 那只能建议看汇编了
Monad
2015-05-23 22:58:17 +08:00
@xylophone21 就因为是Big Endian所以采用ntohs了, Network Byte Order 本来就是Big Endian的嘛

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/193050

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX