1.这种赋值语句是我练习时写的错误代码,它不符合规范,是实际写代码的时候,不应该出现的。只是结果碰巧“正确”,因此拿出来讨论。
2.因此这篇笔记对实际代码能力的提升并没有太大帮助。
下面这段代码,4个printf语句的输出结果分别为多少?
#include<stdio.h>
int main()
{
char *a = ‘abc‘ ;
char b = ‘abc‘ ;
printf( "%s\n", &a); //c
printf( "%c\n", a); //cba
printf( "%s\n", &b); //c [email protected]$#$(乱码) cba
printf( "%c\n", b); //c
return 0;
}
----------------------------------------------------------------------------------------------------------------------------------------------------
从一开始学习C语言中的char变量类型,几乎所有教材都在警告我们,单引号里面只允许存放一个字符
如:
char a = ‘1‘ ;
char a = ‘1‘ ;
然而,当单引号中的内容为若干个字符时,比如
char a = ‘123‘ ;
char a = ‘abc‘ ;
这时编译器并不会报错,而是会在编译的时候弹出警告。(测试环境:VS2015、VC++6.0、vim)
但注意,这种赋值语句是不符合规范的,是实际写代码的时候,不应该出现的。
下面这段代码:
int main()
{
char b = ‘abcd‘ ;
printf( "%c\n", b);
return 0;
}
printf语句输出的结果为字符d
由此可以看出,当我们用这种不规范的方式给一个char类型变量赋值,该变量实际得到的值是我们所赋的那串字符 abcd 的最后一个字符 d
----------------------------------------------------------------------------------------------------------------------------------------------------
现在来看一开始那段代码:
#include<stdio.h>
int main()
{
char *a = ‘abc‘ ;
char b = ‘abc‘ ;
printf( "%s\n", &a); //c
printf( "%c\n", a); //cba
printf( "%s\n", &b); //c [email protected]$#$(乱码) cba
printf( "%c\n", b); //c
return 0;
}
在调试的过程中打开内存,监视到的内存如下:
0x0018FC93 63 cc cc cc cc cc cc cc cc (&b)
0x0018FC9C 63 62 61 00 cc cc cc cc b8 (&a)
通过监视到的内存可以理解printf函数为什么这样输出了。
但是这里又出现了一个问题:
char *a = ‘abc‘ ;
应该可以等同于:
char *a = NULL;
a = ‘abc‘ ;
同样是给一个变量赋值,为什么在内存中存储的方式不一样呢?
既然赋值相同,那么问题就出在变量类型上:
b 是 char类型的变量。
而 a 是 char类型的指针, 本代码中,无法获取 *a 的值,但按照定义, *a才是char类型的变量。而 a 作为指针,默认是一个int类型的变量。
这也解释了 &a 在内存中那个 00 的来源:int类型变量占4个字节,刚才赋值用了3个字节,剩下的一个字节,编译器用 00 补上了
而也正是因为那个‘00’ ,代码中的printf( "%c\n", a); 才能“正常”输出。
明确了这点,将代码修改:
int main()
{
char *a = ‘abcd‘ ;
char b = ‘abcd‘ ;
printf( "%c\n", a);
printf( "%s\n", &a);
printf( "%c\n", b);
printf( "%s\n", &b);
return 0;
}
执行这条代码, 果然,由于4个字节被“填满” printf( "%s\n", &a); 这条语句也无法正常输出了
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
我们都知道,
正常情况下,char类型的变量,在接受赋值的时候,是只接收字符最后一个字节的。
但实际代码执行的时候,它并不是直接去找最后一个字符,
而是从第一个字符开始,逐个读取,每当读取一个字符,就将上一个字符“冲掉”,所以我们看到的永远是最后一个输入的内容。
现在只剩下最后一个问题了:除了最后一个字符,其他字符在哪里存放过,又是如何存放的呢?
再看一遍刚刚调试时的那个代码的内存:
0x0018FC93 63 cc cc cc cc cc cc cc cc (&b)
0x0018FC9C 63 62 61 00 cc cc cc cc b8 (&a)
可以看出,int 类型的 a变量,由于能容纳4个字节,所以并没有把多余的字符“冲掉”。
char 类型的变量 b ,只能容纳一个字节,但从始至终,b变量只存放过 63(c)。
而61 62 则是在 输入缓冲区 内,被先后“冲掉”的。
也就是说,给变量赋值,属于“写入”操作,这种操作并不是直接操作内存,
而是从一块被称为 输入缓冲区 的内存区域来回复制数据,这样的做法有利于提高机器工作效率。
当给int类型变量赋值时,相应的 输入缓冲区 长度为 4,当写满4个字节,再一次性地把这4个字节同时送入要赋值的变量所在的内存。
给 char 类型变量赋值同理,只不过这时 输入缓冲区 的长度为1,每写一个字节,就把前面的字节替代掉,所以最后得到的就是最后一个字节。
最后
这种赋值语句是我练习时写的错误代码,它不符合规范,是实际写代码的时候,不应该出现的。
这种赋值语句是我练习时写的错误代码,它不符合规范,是实际写代码的时候,不应该出现的。
这种赋值语句是我练习时写的错误代码,它不符合规范,是实际写代码的时候,不应该出现的。