C语言精彩编程百例的第7个例子
在C语言中字符存储为整形, 不带限定符的char类型对象是否带符号取决于具体机器(The C Programming Language 2.2节)。
目前还看不出是否带符号带来什么问题,暂时不做深入研究。 不过估计在实际应用中,这样的处理会复杂些,或者明确限定符。
源程序:
#include<stdio.h>
void main()
{
char c1,c2,c3,c4,c5,c6,c7;
c1 = 'C';
c2 = 'h';
c3 = 'i';
c4 = 'n';
c5 = 'e';
c6 = 's';
c7 = 'e';
printf("源码是:%c%c%c%c%c%c%c",c1,c2,c3,c4,c5,c6,c7);
c1 = c1 + 6;
c2 = c2 + 6;
c3 = c3 + 6;
c4 = c4 + 6;
c5 = c5 + 6;
c6 = c6 + 6;
c7 = c7 + 6;
printf("密码是:%c%c%c%c%c%c%c",c1,c2,c3,c4,c5,c6,c7);
}
变量赋值
movb $67, -1(%ebp) # c1
movb $104, -2(%ebp) # c2
movb $105, -3(%ebp) # c3
movb $110, -4(%ebp) # c4
movb $101, -5(%ebp) # c5
movb $115, -6(%ebp) # c6
movb $101, -7(%ebp) # c7
这里看的比较清楚,每一个字符占1byte 内存空间。
printf("源码是:%c%c%c%c%c%c%c",c1,c2,c3,c4,c5,c6,c7);
movsbl -7(%ebp),%eax # printf 参数入栈
pushl %eax
movsbl -6(%ebp),%eax # movsbl 8位数据入32位寄存器,空位补齐就和char是否有符号有关了
pushl %eax
movsbl -5(%ebp),%eax
pushl %eax
movsbl -4(%ebp),%eax
pushl %eax
movsbl -3(%ebp),%eax
pushl %eax
movsbl -2(%ebp),%eax
pushl %eax
movsbl -1(%ebp),%eax
pushl %eax
pushl $LC0
call _printf
addl $32, %esp
printf 函数具体实现,目前还没有能力研究。 看printf传递参数时用到的movsbl, 这里的char编译器处理为有符号数。
将源程序中的变量定义改为 :unsigned char c1,c2,c3,c4,c5,c6,c7;, 对应的汇编代码则改编为:
movb -7(%ebp), %al
pushl %eax
movl $0, %eax
movb -6(%ebp), %al
pushl %eax
movl $0, %eax
movb -5(%ebp), %al
pushl %eax
movl $0, %eax
movb -4(%ebp), %al
pushl %eax
movl $0, %eax
movb -3(%ebp), %al
pushl %eax
movl $0, %eax
movb -2(%ebp), %al
pushl %eax
movl $0, %eax
movb -1(%ebp), %al
pushl %eax
pushl $LC0
call _printf
addl $32, %esp
8位数据存入32位寄存器还是有空位补齐的问题的, 如果用movzbl 替换 , eax 清零 再保存参数,代码修改为:
movzbl -7(%ebp),%eax # printf 参数入栈
pushl %eax
movzbl -6(%ebp),%eax
pushl %eax
movzbl -5(%ebp),%eax
pushl %eax
movzbl -4(%ebp),%eax
pushl %eax
movzbl -3(%ebp),%eax
pushl %eax
movzbl -2(%ebp),%eax
pushl %eax
movzbl -1(%ebp),%eax
pushl %eax
pushl $LC0
call _printf
addl $32, %esp
编译运行后结果保持不变。
最后的确认: 在源程序中声明char 为signed char 对比发现2者没有区别=> 确认: 本编译器认为char 是 signed char 。 singed char 和 unsgined char 在处理方式上有所不同。 由于目前变量的值都没有超过127 (singed char 上限),所以两种数据类型的运行结果没有区别。
编译器版本信息如下: