char的符号,有木有

提及了这个蛋疼的问题,一个被烤焦的问题:默认情况下,在Intel处理器,是有符号的;arm处理器上,却是无符号。

这里还是以arm架构为例,先来个没有任何争议的 n<127

int main(void)
{   
    834c:	e52db004 	push	{fp}		; (str fp, [sp, #-4]!)
    8350:	e28db000 	add	fp, sp, #0	; 0x0
    8354:	e24dd00c 	sub	sp, sp, #12	; 0xc
    char n;
    for (n = 0; n < 127; n++)
    8358:	e3a03000 	mov	r3, #0	; 0x0
    835c:	e54b3005 	strb	r3, [fp, #-5]
    8360:	ea000002 	b	8370 <main+0x24>
    8364:	e55b3005 	ldrb	r3, [fp, #-5]
    8368:	e2833001 	add	r3, r3, #1	; 0x1
    836c:	e54b3005 	strb	r3, [fp, #-5]
    8370:	e55b3005 	ldrb	r3, [fp, #-5]
    8374:	e353007e 	cmp	r3, #126	; 0x7e  //与126比较大小,若小于等于,以下就跳转,形成循环。
    8378:	9afffff9 	bls	8364 <main+0x18>
    {
        ;
    }

    return 0;
    837c:	e3a03000 	mov	r3, #0	; 0x0
}

让我们越过这个signed or unsigned"是非界限",试个 n<129

int main(void)
{   
    834c:	e52db004 	push	{fp}		; (str fp, [sp, #-4]!)
    8350:	e28db000 	add	fp, sp, #0	; 0x0
    8354:	e24dd00c 	sub	sp, sp, #12	; 0xc
    char n;
    for (n = 0; n < 129; n++)
    8358:	e3a03000 	mov	r3, #0	; 0x0
    835c:	e54b3005 	strb	r3, [fp, #-5]
    8360:	ea000002 	b	8370 <main+0x24>
    8364:	e55b3005 	ldrb	r3, [fp, #-5]
    8368:	e2833001 	add	r3, r3, #1	; 0x1
    836c:	e54b3005 	strb	r3, [fp, #-5]
    8370:	e55b3005 	ldrb	r3, [fp, #-5]
    8374:	e3530080 	cmp	r3, #128	; 0x80
    8378:	9afffff9 	bls	8364 <main+0x18>
    {
        ;
    }

    return 0;
    837c:	e3a03000 	mov	r3, #0	; 0x0
}

看来是一模一样。既然默认是unsigned char,也就无所谓与128的比较咯。

再来个 n <128 怎么样?

int main(void)
{   
    834c:	e52db004 	push	{fp}		; (str fp, [sp, #-4]!)
    8350:	e28db000 	add	fp, sp, #0	; 0x0
    8354:	e24dd00c 	sub	sp, sp, #12	; 0xc
    char n;
    for (n = 0; n < 128; n++)
    8358:	e3a03000 	mov	r3, #0	; 0x0
    835c:	e54b3005 	strb	r3, [fp, #-5]
    8360:	ea000002 	b	8370 <main+0x24>
    8364:	e55b3005 	ldrb	r3, [fp, #-5]
    8368:	e2833001 	add	r3, r3, #1	; 0x1
    836c:	e54b3005 	strb	r3, [fp, #-5]
    8370:	e55b3005 	ldrb	r3, [fp, #-5]
    8374:	e1a03c03 	lsl	r3, r3, #24    //这里似乎出现了异常,先左移24位,以下再右移(thumb)24位
    8378:	e1a03c43 	asr	r3, r3, #24    //作用大家都懂得,但既然都unsigned,何必如此折腾?
    837c:	e3530000 	cmp	r3, #0	; 0x0
    8380:	aafffff7 	bge	8364 <main+0x18>
    {
        ;
    }

    return 0;
    8384:	e3a03000 	mov	r3, #0	; 0x0
}
最后,再看看有符号(signed char)的情况:
int main(void)
{   
    834c:	e52db004 	push	{fp}		; (str fp, [sp, #-4]!)
    8350:	e28db000 	add	fp, sp, #0	; 0x0
    8354:	e24dd00c 	sub	sp, sp, #12	; 0xc
    signed char n;	//有符号
    for (n = 0; n < 110; n++)
    8358:	e3a03000 	mov	r3, #0	; 0x0
    835c:	e54b3005 	strb	r3, [fp, #-5]
    8360:	ea000002 	b	8370 <main+0x24>
    8364:	e55b3005 	ldrb	r3, [fp, #-5]
    8368:	e2833001 	add	r3, r3, #1	; 0x1
    836c:	e54b3005 	strb	r3, [fp, #-5]
    8370:	e15b30d5 	ldrsb	r3, [fp, #-5]	//有符号后确实不怎么一样:mem->reg带有了符号标记s
    8374:	e353006d 	cmp	r3, #109	; 0x6d
    8378:	dafffff9 	ble	8364 <main+0x18>
    {
        ;
    }

    return 0;
    837c:	e3a03000 	mov	r3, #0	; 0x0
}


字符有没有符号,其实意义不是很大,本身计算机就把它当做个数字,所谓的printf("%c",ch)也只是将一个0~127的数字经过ascii表翻译成人类能懂的语言罢了。
不过,要记住几点:
通常都会认为char默认有符号,但arm下却是无符号,所以说,这个问题是和体系相关的东西。
对于处理器来说,也就是从汇编指令的角度去看,变量占几个字节,字符有没有符号,是有不同的指令,不同的方式去执行。处理器的心还是很细致di,呵呵。

posted @ 2011-06-24 09:52  郝壹贰叁  阅读(1943)  评论(0编辑  收藏  举报