C语言——printf打印字符串(关于数据在内存中存储格式的体现)

时间:2021-05-13 00:15:26

PS:本篇文章,是笔者在C语言学习过程中的所产生疑惑的地方,经过查阅相关资料得出的结论,如有错误的地方,还望指出改正。

int 占4个字节, 这里输入的8位16进制数每相邻两位数代表一个字节。如:44,43,42,41

int b = 0x41424344;
printf("string: %s\n", &b);

注意:%s打印字符串的时候,必须要求printf所传参数必须是一个内存的地址,且一定有一个0(代表字符串结尾标志‘\0’)做为截至条件。而这里并没有以0结尾所以,这两行代码除了输出各个字节的ASCII码对应的字符以外还会输出这片存储区域后面的的内存所存储的数据(是不可预见的)知道遇到0为止。
我的电脑是小端存储系统,所以输出结果为:
C语言——printf打印字符串(关于数据在内存中存储格式的体现)

下面来看看这些代码:

    int b = 0x41424344;
    int b1 = 0x41424300;
    int b2 = 0x00414243;
    int b3 = 0x41004243;

    printf("string: %s\n", &b);
    printf("string: %s\n", &b1);
    printf("string: %s\n", &b2);
    printf("string: %s\n", &b3);

要记住,%s输出字符串的时候遇到0或‘\0’,就会被截断,只输出0或‘\0’前面的字符,所以,这里b1的最低位为0,则b1没有字符可以输出。b2, b3同理。
如图:C语言——printf打印字符串(关于数据在内存中存储格式的体现)

同样的道理,如下代码:

char arr[4] = {0x41, 'X', '0', 'C'};
        printf("string: %s\n", arr);

由于arr[4]数组只有4个元素,由于赋值的时候就给四个元素都赋了值,数组中就没有元素再来存储结束符‘\0’,所以,同样输出完数组后会有乱码产生。
如图:
C语言——printf打印字符串(关于数据在内存中存储格式的体现)

最有意思的是这两行代码:

int arr[] = {0x41, 'm', 'X', '0', 'C', '\0'};
        printf("string: %s\n", arr);

看上去,在数组的末位手动添加了字符串结尾标志符,以为正常输出:AmX0C
其实不然。
C语言——printf打印字符串(关于数据在内存中存储格式的体现)
这里我给出了,前两个数据在内存中存储的格式,由于int占4个字节,所以0x41只是占用了第一个元素4个字节的第一个字节,所以后面的三个字节由系统自动补0,所以编译器在编译的时候,任然是碰到0就截止。就导致,最终程序只能输出,0x41所对应的字符 ‘A’.
如图:
C语言——printf打印字符串(关于数据在内存中存储格式的体现)

下面提供两种可以正确输出的方式:

    char arr[5] = {0x41, 'm', 'X', '0'};
    char arr2[] = "AX0C";
    printf("string: %s\n", arr);
    printf("string: %s\n", arr2);

C语言——printf打印字符串(关于数据在内存中存储格式的体现)