我想知道是否有一种使用8位数据类型从0到255计数的简洁方法,如:
for(uint8_t i(0);i<=255;++i)
{
....
}
这显然不起作用,但它清楚地表明你想从0到255计数。
一个有效的解决方案就是:
uint8_t i(0);
do
{
...
++i;
}
while(i > 0);
但是在这里它根本不清楚从0到255的数量。
这也可以,但它只是丑陋恕我直言:
uint8_t i(0);
while(true)
{
...
if (i == 255)
{
break;
}
++i;
}
所以我想知道,如果不使用更大的数据类型,有没有一种干净的方法呢?
编辑:
答案 0 :(得分:21)
怎么样:
uint8_t i = 0;
do {
...
} while (i++ != 255);
答案 1 :(得分:8)
我不确定你的意思,但
uint8_t i = 0;
do {
...
} while (++i & 255) ;
应该按照你的要求做,并且明确引用255(如果编译器是C99标准且uint8_t真的是8位,则无用)。
答案 2 :(得分:5)
显而易见的是什么问题?
i = 255;
do {
work();
} while (i--);
答案 3 :(得分:2)
您似乎想通过您正在使用的数据类型传达从0到255计数的消息,但255的重要性是什么?您应该#define这个神奇的数字,并明确说明其目的。此外,声明上方的评论比尝试在某些奇怪的陈述中“编码”所有信息更有帮助。
例如:
#define MAX_RETRIES 255
unsigned int retries;
for(retries = 0; retries <= MAX_RETRIES; ++retries)
{
do_retry_work();
}
如果需要,请添加注释,为什么重试次数限制为255次。
答案 4 :(得分:2)
我建议这个简单的解决方案:
for (int i = 0; i < 256; ++i) {
...
}
可能也是最有效的解决方案。
即使您使用较小的(1字节)数据类型。 C编译器会将其提升为任何表达式中的int。
在8位控制器上,int可能是16位。使用单字节类型只能节省一个字节的堆栈空间。然后编译器可能会将该变量放入寄存器中,因此无论如何都不会节省空间。
检查上面代码生成的汇编代码,然后决定是否需要(空间)优化。
答案 5 :(得分:0)
算上两半?
uint8_t k = 0;
while (k & 0x80 == 0) {
work();
k++;
}
while (k & 0x80 == 1) {
work();
k++;
}
答案 6 :(得分:0)
你花了这么多努力来保存一个字节? 你的最后一个例子是可行的,或者你可以做第一个和第三个的某种组合:
for (uint8_t i = 0;;++i)
{
work();
if (i == 255)
break;
}
尽管如此,问问自己代码中增加的丑陋是否值得保存一个字节。 如果你继续这样的解决方案,你可能应该记录为什么你没有这么做的明显方法。
答案 7 :(得分:0)
for (uint8_t i(0); (int)i <= 255; ++i)
对我来说非常清楚。
即使您尝试使用1字节计数器,您的编译器也可以将其转换为:
for (int ii(0); ii <= 255; ++ii) {
uint8_t i(ii);
...
}
例如,GCC确实如此,因为它更快。
$ cat >test.c void foo(char); void bar(void) { char i; for (i = 0; i <= 255; i++) foo(i); } ^D $ cc -m32 -c -O3 test.c $ objdump -d test.o test.o: file format elf32-i386 Disassembly of section .text: 00000000 <bar>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 53 push %ebx 4: 31 db xor %ebx,%ebx 6: 83 ec 04 sub $0x4,%esp 9: 8d b4 26 00 00 00 00 lea 0x0(%esi,%eiz,1),%esi 10: 89 1c 24 mov %ebx,(%esp) 13: 83 c3 01 add $0x1,%ebx 16: e8 fc ff ff ff call 17 <bar+0x17> 1b: eb f3 jmp 10 <bar+0x10> $ cc -m64 -c -O3 test.c $ objdump -d test.o test.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <bar>: 0: 53 push %rbx 1: 31 db xor %ebx,%ebx 3: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 8: 89 df mov %ebx,%edi a: 83 c3 01 add $0x1,%ebx d: e8 00 00 00 00 callq 12 <bar+0x12> 12: eb f4 jmp 8 <bar+0x8>
答案 8 :(得分:0)
如果你想清除不太清晰的代码,你可能总是添加评论;)
一种解决方案是将循环体放在一个函数中(如果不考虑公共鞭,则为宏),然后:
uint8_t i ;
for( i = 0; i < 255; i++ )
{
body(i) ;
}
body(i) ;
或者如果您不想扩展i
的范围并且适用C ++范围规则:
for( uint8_t i = 0; i < 255; i++ )
{
body(i) ;
}
body(255) ;
答案 9 :(得分:0)
不,在普通旧C中没有明确的方法,因为在增量后检查条件,如果比较&lt; = 255,你将永远循环,因为8位值不能超过255并终止
所以它变成了。
uint8_t i = 0;
while (1)
{
/* your stuff */
if (255 == i++)
break;
}
除非你认为在你的书中清楚地检查0(看到环绕)。我的目前尚不清楚。
请注意,8位类型在许多编译器上效率非常低,有时会产生不必要的符号扩展。您可能希望使用uint_least8_t类型,它可能会扩展到系统的字大小并且运行得更快。