免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4357 | 回复: 13

小心char类型带来的麻烦 [复制链接]

论坛徽章:
0
发表于 2009-03-16 22:47 |显示全部楼层
char的类型有几种呢?无非是unsigned char 和signed char,是吧。让我们用下面的程序来做个测试
template<typename T>
struct Type
{
    inline
static
void print()
    {
        std::cout
<<
"Unknow"
<< std::endl;
    }
};

template
<>
struct Type<signed char>
{
    inline
static
void print()
    {
        std::cout
<<
"signed char"
<< std::endl;
    }
};

template
<>
struct Type<unsigned char>
{
    inline
static
void print()
    {
        std::cout
<<
"unsigned char"
<< std::endl;
    }
};

int main()
{
    Type<unsigned char>::print();
    Type
<signed char>::print();
    Type
<char>::print();
   
   
return
0;
}


输出内容:
unsigned char
signed char
Unknow

结果出乎意料,输出内容说明编译器把unsigned char、signed char和char识别成三种不同的类型。
那么char类型是有符号还是无符号呢?通过下面的程序来求证一下(以下程序在Microsoft visual C++ 2003、windows 2003下编译并运行)。


int main()
{
   
char c   =
-1;
   
int i    = c;

    std::cout
<< i << std::endl;

   
return
0;
}


输出内容:
-1

输出内容证明char是有符号的,但这并不可靠,各家的编译器不保证 char都是signed或unsigned。可以用IDE修改char有符号还是无符号,在Microsoft visual C++ 2003中, 通过“项目->属性->C/C++->语言->默认char无符号”进行修改

总结:

C+ +中char、unsigned char和signed char是三种类型,因此在函数重载和模板偏特化时,应注意重写它们的三个版本。虽然它们是三种类型,但char不是unsigned char就是signed char,且char是否有符号可由编译器改变。因此不因编写依赖char是有符号还是无符号的代码。

论坛徽章:
0
发表于 2009-03-16 23:00 |显示全部楼层
啊?!
原以为语法层面上,我已经无所不知了,谢谢楼主!!

论坛徽章:
0
发表于 2009-03-16 23:11 |显示全部楼层
那么.............. lz 可以给出一个通用的解决方案么?

论坛徽章:
0
发表于 2009-03-16 23:16 |显示全部楼层
原帖由 prolj 于 2009-3-16 23:11 发表
那么.............. lz 可以给出一个通用的解决方案么?


这个通用方案当面试题不错

论坛徽章:
0
发表于 2009-03-16 23:34 |显示全部楼层
在楼主的提示下,我查了一下 gcc 的参数,原来它支持 -fsigned-char 和 -funsigned-char

printf("%d\n", '\376') 在 -funsigned-char 打开时输出 254,不打开或打开 -fsigned-char 时输出 -2.

也请参考下贴:

http://bbs2.chinaunix.net/thread-1394046-1-1.html

论坛徽章:
0
发表于 2009-03-17 10:15 |显示全部楼层

说一下我的看法

首先 unsigned char 和 signed char 是两种不同的类型,我想这个没什么好说的。
然后,至于lz第一个例子中,char被识别为了 "Unknown",我想这可能并不是因为char是 unsigned char 和 signed char 之外的第三种类型,而是编译器在做语法扫描时,没有先将 char 根据编译设置映射为  unsigned char 或 signed char, 而是先进性模版的文本文字匹配。之后才进行的类型映射转换。

至于第二个例子。很明显是符号位扩展的结果。

另外,lz的总结基本上是对的。但好像逻辑上有点小的混乱。前面说是三种类型,但后面又说“但char不是unsigned char就是signed char”,那就是说,是三种表象,两种类型。:wink:

论坛徽章:
0
发表于 2009-03-17 10:30 |显示全部楼层
原帖由 swxlion 于 2009-3-17 10:15 发表
... 至于第二个例子。很明显是符号位扩展的结果。 ...


关于这一点,我写了一个例子,我想足够可以说明问题。lz可以参考一下:
#include <iostream>
using std::cout;
using std::endl;

template <typename A, typename B>
void test()
{
&nbsp;&nbsp;&nbsp;&nbsp;A c = -1;
&nbsp;&nbsp;&nbsp;&nbsp;B i = c;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;cout<<i<<endl;
}

int main()
{
&nbsp;&nbsp;&nbsp;&nbsp;test<char, int>();
&nbsp;&nbsp;&nbsp;&nbsp;test<char, unsigned int>();
&nbsp;&nbsp;&nbsp;&nbsp;test<unsigned char, int>();
&nbsp;&nbsp;&nbsp;&nbsp;test<unsigned char, unsigned int>();
&nbsp;&nbsp;&nbsp;&nbsp;test<signed char, int>();
&nbsp;&nbsp;&nbsp;&nbsp;test<signed char, unsigned int>();
&nbsp;&nbsp;&nbsp;&nbsp;return 0;
}

论坛徽章:
0
发表于 2009-03-17 10:35 |显示全部楼层

忘了给结果了

原帖由 swxlion 于 2009-3-17 10:30 发表


关于这一点,我写了一个例子,我想足够可以说明问题。lz可以参考一下:
#include
using std::cout;
using std::endl;

template
void test()
{
    A c = -1;
   ...


不好意思,刚才忘了给结果了。
在32位的机器上,对char的有无符号是用默认设置的情况下,输出为:

  1. -1
  2. 4294967295
  3. 255
  4. 255
  5. -1
  6. 4294967295
复制代码


也就是说,其实不是类型A在起作用,而是类型B,决定了是否符号位扩展。
而lz的第二个例子里类型 B 用的是 int 类型,int 在我当前编译器上是有符号数,所以发生了符号位扩展。
这也就是我前面所说。

不过,楼主的研究精神非常可嘉!
没想到把我的胃口都吊起来了~~~
MS这是lz的第一篇帖子。不妨加精?

[ 本帖最后由 swxlion 于 2009-3-17 10:37 编辑 ]

论坛徽章:
0
发表于 2009-03-17 21:56 |显示全部楼层

回复 #3 prolj 的帖子

这其实也是个移植的问题。
1.保证一个原则。不编写依赖char是有符号还是无符号的代码。
就是说,如果不是把char当成字符串来用,而是当成一个数值来使用。
就要注意char的符号性。尤其注意如果存在char类型的变量和其他类型变量的比较(即存在对char的隐式类型转换时)。
2.各种机器都有自己缺省的char类型.既可能是unsigned char也可能是signed char .
理想情况下,当依赖于数据的符号性时,一个可移植程序总是应该使用signed char或unsigned char.
但是许多程序已经写成只用简单的char,并且期待这是有符号数(或者无符号数,具体情况取决于 编写程序的目标机器).
并且编译器和程序对char类型的期待是不同的话。那么移植时就要注意所有char类型的变量是否被正确的编码。

[ 本帖最后由 hitraistlin 于 2009-3-17 22:23 编辑 ]

论坛徽章:
0
发表于 2009-03-17 21:57 |显示全部楼层

回复 #8 swxlion 的帖子

其实第二个例子,就是利用符号位扩展的特性来判断当前编译器把char类型变量当作有符号还是无符号。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP