【C语言进阶剖析】14、单引号和双引号

C 语言中的单引号用来表示字符字面量
C 语言中的双引号用来表示字符串字面量

举例说明:

  • ‘a’ 表示字符自变量,在内存中占 1 字节,‘a’ + 1 表示 ‘a’ 的 ASCII 码加 1,结果为 ‘b’
  • “a” 表示字符串字面量,在内存中占 2 个字节,“a”+1 表示指针运算,结果指向 “a” 结束符 ‘\0’

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 行会引起段错误,下面我们就来分析一下原因,在此之前补充一个小贴士:

小贴士

  1. 字符字面量被编译为对应的 ASCII 码
  2. 字符串字面量被编译为对应的内存地址
  3. printf 的第一个参数被当作字符串内存地址
  4. 内存的低地址空间不能在程序中任意访问

带着上面的小贴士,将 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 编译器允许字符串对字符变量赋值,只能得到错误

最后补充一下程序的地址空间分布
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值