C语言的单引号问题

C语言的单引号问题

单引号的原理

C语言的单引号实际上时将' '内的字符转化为ASCII码对应的整型值,并且在存储时占据一个字节,即sizeof(char)

// 第一个例子
int main()
{
    char ch;
    ch = '?';
    printf("%d, %c", ch, ch);
    // 63, ?
}

输出63, ?
这是因为?对应的ASCII码值为63

现在来看看一个单引号中有两位字符时的情况

// 第二个例子
int main()
{
    char ch;
    ch = '!?';
    printf("%d, %c", ch, ch);
    // 63, ?
}

输出竟然还是63, ?

先别急着追问为什么,我们再来看看下一种有些差异的情况

// 第三个例子
int main()
{
    printf("%d, %c",'!?','!?'); 
    // 这次的输出变成了8511, ?
}

这其实和上述的原理' '中的字符会被转化为ASCII的整型值 一致
我们来看看8511是如何得到的,从ASCII表上,我们得到!对应33?对应63
按一个字符一个字节转化为二进制就分别是0010 00010011 1111,将它们拼接得到0010 0001 0011 1111,转换为十进制我们得到8511

这就是8511的由来,那为什么在第二个例子中的输出不一样呢?
原来是8511赋值给char类型时发生了溢出,得到的结果就是0011 1111这一个字节,也就是63,从结果上看char得到的就是单引号中的最后一个字符

知道原理后可以用更简便的方式计算,一个数向左移一个字节<< 8,相当于乘以2 ^ 8 = 256

'!?' = 8511
33 * 256 + 63 = 8511
'xyz' = 7895418
120 * 256 * 256 + 121 * 256 + 122 = 7895418
'456789' = 909588537
这次整型值也溢出了,'456789' = '6789' = 909588537

int和char

int和char在很多方面都是相同的

int main()
{
    printf("%d, %c\n", 65, 65);
    printf("%d, %c\n", 100, 100);
    printf("%d, %c\n", 1000, 1000);
    printf("%d, %c\n", 10000, 10000);
    /* 
    输出
    65, A
    100, d
    1000, ?
    10000, 
    */ 
}

比如:

  • 都使用二进制补码法表示正负数;

  • char可以用%d输出ASCII码,小的整数也可以用%c输出字符,大的字符使用%c相当于经过了一次溢出处理,同样也会输出某个字符。

    它们最主要的区别在于int占4个字节,而char占1个字节,理论上'xxxx'(x表示一个字符)可以表示一个int

更复杂的情况

基于以上理论,我们可以有一个有趣的玩法

int main()
{
    int a[] = {'1234', 'abcd', 'qwer', 'hjkl', 0};
    printf("%s", a);
}

在我的电脑上,这输出4321dcbarewqlkjh
%s实际上也是通过字符指针,来一个个输出字符的,在这个过程中,实际上可以理解为发生了

a = (char *) a

'1234', 'abcd'等经过单引号转变为连续排列的一个个字节,这和字符串的储存方式很像,同时我还加了一个0来结束%s的输出,这就更像了。

可以看到,输出和我们初始化的数字是倒置的,这说明整型的存储是反向的。也就是说在整型存储时,低位字节存在前面的地址,高位字节存在后面的字节。

int main()
{
    int a[] = {'1234', 0};
    printf("%s\n", a);
    // 4321
    a[0] <<= 1;
    printf("%s\n", a);
    // hfdb
}

再找出它们对应的二进制
'1234'对应0011 0001 0011 0010 0011 0011 0011 0100
'4321'对应0011 0100 0011 0011 0011 0010 0011 0001
'hfdb'对应0110 1000 0110 0110 0110 0100 0110 0010
'hfdb'确实是'4321'左移一位后的结果。

posted @ 2022-10-27 11:46  Violeshnv  阅读(69)  评论(0编辑  收藏  举报