C 清除使用8位数据类型从0到255计数的代码
我想知道是否有一种干净的方法可以使用8位数据类型从0计数到255,比如:C 清除使用8位数据类型从0到255计数的代码,c,embedded,microcontroller,C,Embedded,Microcontroller,我想知道是否有一种干净的方法可以使用8位数据类型从0计数到255,比如: for(uint8_t i(0);i<=255;++i) { .... } uint8_t i(0); do { ... ++i; } while(i > 0); 但这里根本不清楚它的计数范围是从0到255 这也会起作用,但它只是丑陋的IMHO: uint8_t i(0); while(true) { ... if (i == 255) { b
for(uint8_t i(0);i<=255;++i)
{
....
}
uint8_t i(0);
do
{
...
++i;
}
while(i > 0);
但这里根本不清楚它的计数范围是从0到255
这也会起作用,但它只是丑陋的IMHO:
uint8_t i(0);
while(true)
{
...
if (i == 255)
{
break;
}
++i;
}
所以我想知道,有没有一种干净的方法可以在不使用更大数据类型的情况下做到这一点
编辑:
- 我喜欢使用的版本,因为它不用思考就能清楚地表明其意图:从0循环到255。所有其他版本都需要对正在发生的事情进行一些思考,因此更容易混淆其他版本
- 我不想使用int,因为代码是针对内存不多的8位微控制器的
uint8_t k = 0;
while (k & 0x80 == 0) {
work();
k++;
}
while (k & 0x80 == 1) {
work();
k++;
}
我不知道你的意思,但是
uint8_t i = 0;
do {
...
} while (++i & 255) ;
应该按照你的要求去做,并且有一个对255的明确引用(如果你的编译器是C99标准的,uint8\u t实际上是8位的话,那就没用了)。你花了这么多精力来节省一个字节? 您的最后一个示例将起作用,或者您可以将第一个和第三个示例进行某种组合:
for (uint8_t i = 0;;++i)
{
work();
if (i == 255)
break;
}
不过,问问自己,代码中增加的丑陋是否值得保存这一字节。
如果你真的同意这样的解决方案,你可能应该记录下为什么你没有用显而易见的方式来解决问题。那么:
uint8_t i = 0;
do {
...
} while (i++ != 255);
明显的错误是什么
i = 255;
do {
work();
} while (i--);
您似乎希望通过使用的数据类型传达从0到255计数的信息,但是255的意义是什么?你可能应该用一个明确说明其用途的名字来定义这个神奇的数字。此外,在语句上方添加一条注释比试图将所有这些信息“编码”到看起来有些怪异的语句中要有用得多 例如:
#define MAX_RETRIES 255
unsigned int retries;
for(retries = 0; retries <= MAX_RETRIES; ++retries)
{
do_retry_work();
}
#定义最大重试次数255次
无符号整数重试;
对于(重试次数=0;重试次数
for(uint8_t i(0);(int)i如果您想使代码不太清晰,您可以始终添加注释;)
一种解决方案是将循环体放在函数中(如果不考虑公开鞭笞,则放在宏中),然后:
uint8_t i ;
for( i = 0; i < 255; i++ )
{
body(i) ;
}
body(i) ;
不,在纯旧C中没有明确的方法,因为条件是在增量后检查的,如果比较,我建议简单的解决方案:
for (int i = 0; i < 256; ++i) {
...
}
for(int i=0;i<256;++i){
...
}
也可能是最有效的解决方案
即使使用较小的(1字节)数据类型,C编译器也会在任何表达式中将其提升为int
在8位控制器上,int可能是16位。使用单字节类型只会节省一个字节的堆栈空间。然后,编译器可能会将该变量放入寄存器,因此不会节省任何空间
检查由上述代码生成的汇编代码,然后决定是否需要(空间)优化。uint8_t i(0);
在CYeah中是一个语法错误,这肯定不是ANSI C。基本上可以使用断点。最好使用结构正确的for()或while()。是有人用8051或什么折磨你吗?@endolith:for循环只有在i>=256
时才会退出。因为i
是一个8位数据类型,它只能保存0..255。如果i==255
而你这样做了i++
它将溢出,然后i==0
,for循环将永远不存在。在这种情况下,i
不能存在r保留退出循环所需的256。@endolith:是的,在求值时转换(如果可能)是没有帮助的,因为i
仍然不能保留255以上的值。您可能可以手动执行类似于int t(i),t++,t+1i这样的操作!我甚至可以在(++i);
你认为标题中的“使用8位数据类型”是什么意思?:-)当然是8位。@paxdiablo:遗憾的是,我看到编译器在类型上有一些自由。希望情况不再如此,人们可以相信uint8_t在255:)之后会取整为0。事实上,一个好的编译器应该使用0xFF消除and,这样留下它就不会有伤害(以防万一)…我喜欢这个,但我更喜欢ots版本,因为它还可以计算255C以外的其他值。飞思卡尔DSP563XX处理器的C编译器(任务)使用本机24位处理器字作为字符类型。它不会从255换行为零,除非您添加一个模糊的编译器选项,该选项在每次值递增时添加一个显式检查。检查所有字符操作的代码大小和处理时间的成本是可怕的。并非所有处理器都是x86或ARM。顺便说一下,这是许多ARM程序员使用的,因为ARM的特殊性。它有什么问题?你倒计时,他的要求是0到255,这一事实又如何呢?@senfo:那么用~i
替换循环中i
的所有用法。没问题!不,我不想通过数据类型传递消息。我想传达的信息是,它从0到255计数,同时使用尽可能最小的数据类型,而不使用复杂的结构。这就是问题所在,我想保存一个字节(微型微控制器),但我仍然希望有清晰的代码OK,但您可能需要实际检查生成的代码。您可能实际上正在丢失生成代码中的空间。少用一个字节存储数据并不能保证最终能节省任何空间,这只是另一个256次的选择。我不会在真正的代码中使用它。
$ 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>
uint8_t i ;
for( i = 0; i < 255; i++ )
{
body(i) ;
}
body(i) ;
for( uint8_t i = 0; i < 255; i++ )
{
body(i) ;
}
body(255) ;
uint8_t i = 0;
while (1)
{
/* your stuff */
if (255 == i++)
break;
}
for (int i = 0; i < 256; ++i) {
...
}