【问题标题】:Separate signed int into bytes in NXC在 NXC 中将带符号的 int 分隔为字节
【发布时间】:2011-04-25 05:47:57
【问题描述】:

NXC 中有什么方法可以将有符号整数转换为字节数组?由于语言限制,我也不能使用显式类型转换或指针。

我试过了:

for(unsigned long i = 1; i <= 2; i++)
{
    MM_mem[id.idx] = ((val & (0xFF << ((2 - i) * 8)))) >> ((2 - i) * 8));

    id.idx++;
}

但是失败了。

编辑:这行得通...只是没有下载。我浪费了大约一个小时试图弄清楚。 >_>


编辑:在 NXC 中,&gt;&gt; 是算术移位。 int 是带符号的 16 位整数类型。 byteunsigned char 相同。


NXC 是 'Not eXactly C',是 C 的亲戚,但与 C 截然不同。

【问题讨论】:

  • 我想没有人会添加标签nxc? :)
  • 为您创建了 [nxc] 标签,删除了不准确的 [c] 标签。
  • 什么是nxc,为什么比原来的标签c更合适?谷歌救援:nxc 是 'Not eXactly C':参见 bricxcc.sourceforge.net/nbc 等。
  • @Jonathan 这是 LEGO Mindstorms NXT 的 ["非官方"] 语言。它代表Not eXactly C

标签: nxt nxc


【解决方案1】:

怎么样

    unsigned char b[4];

    b[0] = (x & 0xFF000000) >> 24;
    b[1] = (x & 0x00FF0000) >> 16;
    b[2] = (x & 0x0000FF00) >> 8;
    b[3] = x & 0xFF;

【讨论】:

  • 您假设目标体系结构具有 32 位长类型。
  • @djs 我什么都不假设。他没有具体说明,所以我展示了一种可能性。由此,他肯定可以根据他的字长/字节顺序进行调整。
  • @cnicutar 就我们所知,他的问题是他认为它是 32 位的。也就是说,我认为我们还没有确定他在询问 C。
  • @djs 我确信掩码和移位的概念足够通用。
  • 哦等等... 有人拔掉了 USB,所以它没有下载。它有效,我很快就会接受。
【解决方案2】:

在 NXC 中使用底层 VM 中可用的操作码执行此操作的最佳方法是使用 FlattenVar 将任何类型转换为字符串(也就是在末尾添加 null 的字节数组)。它会导致单个 VM 操作码操作,其中使用移位和逻辑 AND 和数组操作的任何上述选项都需要数十行汇编语言。

task main()
{
  int x = Random(); // 16 bit random number - could be negative
  string data;
  data = FlattenVar(x); // convert type to byte array with trailing null
  NumOut(0, LCD_LINE1, x);
  for (int i=0; i < ArrayLen(data)-1; i++)
  {
#ifdef __ENHANCED_FIRMWARE
    TextOut(0, LCD_LINE2-8*i, FormatNum("0x%2.2x", data[i]));
#else
    NumOut(0, LCD_LINE2-8*i, data[i]);
#endif
  }
  Wait(SEC_4);
}

获得 LEGO MINDSTORMS 和 NXT 和 Not eXactly C 帮助的最佳方式是通过思维板论坛http://forums.mindboards.net/

【讨论】:

    【解决方案3】:

    问题最初标记为;此答案可能不适用于 Not eXactly C。

    这是什么问题:

    int value;
    char bytes[sizeof(int)];
    
    bytes[0] = (value >>  0) & 0xFF;
    bytes[1] = (value >>  8) & 0xFF;
    bytes[2] = (value >> 16) & 0xFF;
    bytes[3] = (value >> 24) & 0xFF;
    

    您可以将其视为展开的循环。零移位可以省略;优化器肯定会这样做。即使未定义右移负值的结果,也没有问题,因为此代码只访问定义了行为的位。

    此代码以 little-endian 顺序给出字节 - 最低有效字节在 bytes[0] 中。显然,大端顺序是通过以下方式实现的:

    int value;
    char bytes[sizeof(int)];
    
    bytes[3] = (value >>  0) & 0xFF;
    bytes[2] = (value >>  8) & 0xFF;
    bytes[1] = (value >> 16) & 0xFF;
    bytes[0] = (value >> 24) & 0xFF;
    

    【讨论】:

    • 完全迂腐(如果我们谈论 C),没有“定义行为的位”(C1x 中的第 6.5.7 节,但相同的文本出现在 C99 中): “如果 [左操作数] 具有带符号类型和负值,结果值是实现定义的。”也就是说,这个问题似乎完全是关于其他语言的。
    • @Stephen:是的,尽管基本问题通常是在 CPU(汇编)级别使用算术移位还是逻辑移位,区别在于传播符号位还是零位;但结果是高位全为零或全为一(它是实现定义的 - 不是未定义或未指定的 - 它是)。但是,显示的代码不访问高位。不过,您在技术上是正确的 - 标准并没有说明会发生什么,但它确实需要实现来记录会发生什么。
    • 绝对;我只是指出,实现可以记录负值的右移可以产生陷阱表示,或者从/dev/random 返回位,或者做任何其他事情,并且仍然在标准范围内。但是,由于问题实际上似乎与 C 语言无关,所以这不是重点。
    • 不,NXC 使用 [a bizarre form of :)] 算术移位,这不起作用。
    • @muntoo:NXC 手册并没有表明移位运算符有什么奇怪的地方——唯一有点不寻常的特征是 int 类型是 16 位而不是上面假设的 32 位,并且这在桌面计算领域是不寻常的;在使用 NXC 的硬件嵌入式计算领域,我怀疑 16 位 int 仍然相当普遍。 NXC 手册不是独立的;它没有涵盖语言行为的很多细节。
    猜你喜欢
    • 2018-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-23
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    相关资源
    最近更新 更多