概述
C 语言中的单引号用来表示字符字面量
C 语言中的双引号用来表示字符串字面量
举例说明:
- ‘a’ 表示字符自变量,在内存中占 1 字节,‘a’ + 1 表示 ‘a’ 的 ASCII 码加 1,结果为 ‘b’
- “a” 表示字符串字面量,在内存中占 2 个字节,“a”+1 表示指针运算,结果指向 “a” 结束符 ‘ ’
1 实验一:单引号和双引号的本质
//14-1.c
#include<stdio.h>
int main(){
char* p1 = 1;
char* p2 = '1';
char* p3 = "1";
printf("p1 = %s, p2 = %s, p3 = %s", p1, p2, p3);
printf('n');
printf("n");
return 0;
}
1、编译运行结果如下:
可以看出程序第 4、5、8 行给出警告,运行,有段错误。
2、注释第 8、9 行,再次编译运行
//14-1.c
#include<stdio.h>
int main(){
char* p1 = 1;
char* p2 = '1';
char* p3 = "1";
printf("p1 = %s, p2 = %s, p3 = %s", p1, p2, p3);
// printf('n');
// printf("n");
return 0;
}
程序第 4、5 行给出警告,运行,段错误。
3、注释第 7、9 行,再次编译运行
//14-1.c
#include<stdio.h>
int main(){
char* p1 = 1;
char* p2 = '1';
char* p3 = "1";
// printf("p1 = %s, p2 = %s, p3 = %s", p1, p2, p3);
printf('n');
// printf("n");
return 0;
}
程序第 4、5、8 行给出警告,运行,段错误。
4、注释第 7、8 行,再次编译运行。
//14-1.c
#include<stdio.h>
int main(){
char* p1 = 1;
char* p2 = '1';
char* p3 = "1";
// printf("p1 = %s, p2 = %s, p3 = %s", p1, p2, p3);
// printf('n');
printf("n");
return 0;
}
可以看出程序第 4、5 行给出警告,运行,没有问题。
由上可以看出,程序第 4、5、8 行给出警告,程序第 7、8 行会引起段错误,下面我们就来分析一下原因,在此之前补充一个小贴士:
小贴士:
- 字符字面量被编译为对应的 ASCII 码
- 字符串字面量被编译为对应的内存地址
- printf 的第一个参数被当作字符串内存地址
- 内存的低地址空间不能在程序中任意访问
带着上面的小贴士,将 p1, p2, p3 变量对应的地址空间画出来,如下图所示:
打印的 ‘n’ 和 “n” 在内存中地址如下:
p1 的数字 1 和 p2 的字符 ‘1’(对应ASCII 为 0x31),都被当作地址值,直接指向内存;而字符串 “1” 是一个字符串,p3 是该字符串在内存中的地址。地址 0x08048000 是个特殊的地址空间,低于该地址空间的地址都不能任意访问,所以编译语句 char* p1 = 1; char* p2 = ‘1’ 和 printf(’n’) 都给出警告,运行语句 printf(“p1 = %s, p2 = %s, p3 = %s”, p1, p2, p3) 和 printf(’n’) 给出段错误的提示,因为低地址空间不能在程序中任意访问。
2 实验二:混淆概念的代码
再看一个例子,直接看代码。这段代码的本意是如果输入Tab 键、空格、回车,就继续输入。
//14-2.c
#include<stdio.h>
int main(){
char c = " ";
while((c == "t") || (c == " ") || (c == "n")){
scanf("%c", &c);
}
return 0;
}
编译,出现警告,运行,没有任何输入,程序直接退出了,说明 while 循环没有执行。
下面我们来分析一下 char c = “string”; 到底发生了什么?
- 编译后的字符串 “string” 的内存地址被赋值给变量 c
- 内存地址占用 4 个字节,而变量 c 只占用 1 个字节
- 由于类型不同,赋值后产生截断
所以判断循环的三个条件均不满足,while 循环没有执行,如何修改上述代码呢,很简单,把双引号变成单引号即可。
#include<stdio.h>
int main(){
char c = ' ';
while((c == 't') || (c == ' ') || (c == 'n')){
scanf("%c", &c);
}
return 0;
}
3 小结
1、单引号括起来的单个字符代表整数
2、双引号括起来的字符代表字符指针
3、C 编译器接受字符和字符串的比较,无任何意义
4、C 编译器允许字符串对字符变量赋值,只能得到错误
最后补充一下程序的地址空间分布
最后
以上就是酷炫高山为你收集整理的【C语言进阶剖析】14、单引号和双引号的全部内容,希望文章能够帮你解决【C语言进阶剖析】14、单引号和双引号所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复