unicode字符代码的int和char强制转换

本文关键字:char 转换 int 字符 代码 unicode | 更新日期: 2023-09-27 17:49:58

谁能解释一下这段代码到底是怎么回事?

var letter= 'J';
char c = (char)(0x000000ff & (uint)letter);

我理解它正在获得字符的unicode表示,但是我不完全理解:

的作用
(0x000000ff & (uint)letter

0x000000ff和将字母转换为(uint)的目的是什么?是否有一种简便的方法可以实现相同的结果?

感谢

更新

好,看起来大多数人认为这是一个不好的例子,我不想包括整个类,但我想我可能会让你看到的背景。来自参考源的WebHeaderCollection:

  private static string CheckBadChars(string name, bool isHeaderValue)
    {
        if (name == null || name.Length == 0)
        {
            // emtpy name is invlaid
            if (!isHeaderValue)
            {
                throw name == null ? 
                    new ArgumentNullException("name") :
                    new ArgumentException(SR.GetString(SR.WebHeaderEmptyStringCall, "name"), "name");
            }
            // empty value is OK
            return string.Empty;
        }
        if (isHeaderValue)
        {
            // VALUE check
            // Trim spaces from both ends
            name = name.Trim(HttpTrimCharacters);
            // First, check for correctly formed multi-line value
            // Second, check for absenece of CTL characters
            int crlf = 0;
            for (int i = 0; i < name.Length; ++i)
            {
                char c = (char)(0x000000ff & (uint)name[i]);
                switch (crlf)
                {
                    case 0:
                        if (c == ''r')
                        {
                            crlf = 1;
                        }
                        else if (c == ''n')
                        {
                            // Technically this is bad HTTP.  But it would be a breaking change to throw here.
                            // Is there an exploit?
                            crlf = 2;
                        }
                        else if (c == 127 || (c < ' ' && c != ''t'))
                        {
                            throw new ArgumentException(SR.GetString(SR.WebHeaderInvalidControlChars), "value");
                        }
                        break;
                    case 1:
                        if (c == ''n')
                        {
                            crlf = 2;
                            break;
                        }
                        throw new ArgumentException(SR.GetString(SR.WebHeaderInvalidCRLFChars), "value");
                    case 2:
                        if (c == ' ' || c == ''t')
                        {
                            crlf = 0;
                            break;
                        }
                        throw new ArgumentException(SR.GetString(SR.WebHeaderInvalidCRLFChars), "value");
                }
            }
            if (crlf != 0)
            {
                throw new ArgumentException(SR.GetString(SR.WebHeaderInvalidCRLFChars), "value");
            }
        }
        else
        {
            // NAME check
            // First, check for absence of separators and spaces
            if (name.IndexOfAny(InvalidParamChars) != -1)
            {
                throw new ArgumentException(SR.GetString(SR.WebHeaderInvalidHeaderChars), "name");
            }
            // Second, check for non CTL ASCII-7 characters (32-126)
            if (ContainsNonAsciiChars(name))
            {
                throw new ArgumentException(SR.GetString(SR.WebHeaderInvalidNonAsciiChars), "name");
            }
        }
        return name;
    }

感兴趣的位是:

char c = (char)(0x000000ff & (uint)name[i]);

unicode字符代码的int和char强制转换

您正在解析HTTP标头,对吗?这意味着不应该使用(任何)unicode编码。

HTTP报头必须是7位ASCII(不像请求数据)1。这意味着您应该使用ASCII编码而不是默认编码。因此,在解析请求字节时,必须使用Encoding.ASCII.GetString而不是Encoding.Default.GetString。希望您没有使用StreamReader -这将是一个坏主意,原因有很多,包括(可能)头和请求内容之间的编码不匹配。

编辑:

至于在微软源代码中的使用-是的,它发生了。不要试图复制这些东西-它一个hack。请记住,您没有微软工程师所拥有的测试套件和质量保证,所以即使它确实有效,您最好不要复制这样的hack。

我假设它是以这种方式处理的,因为使用string原则上应该是"ASCII字符串"或只是byte[] -因为。net只支持unicode字符串,这被视为较小的邪恶(确实,这就是为什么代码显式检查string 包含任何unicode字符-很清楚头必须是ASCII -如果字符串有任何非ASCII字符,它将显式失败。在为其他人编写高性能框架时,这只是通常的权衡。

脚注:

  1. 实际上,RFC(2616)指定US-ASCII作为编码,可能是指ISO-8859-1。然而,RFC并不是一个有约束力的标准(它更像是一种从混乱中整理秩序的希望:D),而且周围有很多HTTP/1.0和HTTP/1.1客户端(和服务器)实际上并不尊重这一点。像。net的作者一样,我坚持使用7位ASCII(当然是按每字节字符编码,而不是真正的 7位)。

0x000000ff和将字母转换为(uint)的目的是什么

从[0..][255] range: char占用2字节内存

例如:

var letter= (char)4200; // ၩ
char c = (char)(0x000000ff & (uint)letter); // h
// or
// char c = (char)(0x00ff & (ushort)letter);
// ushort (2-byte unsigned integer) is enough: uint is 4-byte unsigned integer

这段代码所做的不是转换为Unicode。

部分0x000000ff &基本上丢弃了unicode字母的第二个字节,并将其转换为只有一个字节长的字母。或者更准确地说:它只保留最有意义的字节,而丢弃其他所有字节——这对于char来说是一样的,因为它的大小是两个字节。

我仍然认为这没有意义,因为它会导致误报:实际上使用两个字节的Unicode字母只会丢失其中一个字节,因此变成一个不同的字母
我会简单地去掉这些代码,在使用c的地方使用name[i]