【 C 】字符串常量
当一个字符串常量出现在表达式中时,它的值是个指针常量。编译器把这些指定字符的一份拷贝存储在内存的某个位置,并存储一个指向第一个字符的指针。但是,当数组名用于表达式中时,它们的值也是个指针常量。我们可以对它们进行下标引用、间接访问以及指针运算。
这些操作对于字符串常量是不是也有意义呢?
看看下面这个表达式是什么意思?
"xyz" + 1
看上去像是一个垃圾!它好像是试图在一个字符串上面执行某种类型的加法运算。
但是,当你记得字符串常量实际上是一个指针常量时,它的意义就变得清楚了。这个表达式计算“指针值 + 1”的值。它的结果是个指针,指向字符串的第二个字符:y。
那么这个表达式又是什么呢?
*"xyz"
理解了第一个,后面的都好说:对一个指针执行间接访问时,其结果就是该指针指向的值。字符串常量的类型是指向字符的指针,所以这个间接访问得到的结果是字符‘x’。
我们继续放出大招:
"xyz"[2]
很简单,对一个指针进行下标访问是合理的,就像数组名也是一个指针常量,对其下标访问就是对数组中的元素进行访问,这个同理,表达式的值为一个字符‘z’。
下面给出一个错误的例子:
*( "xyz" + 4 )
这个表达式的结果是什么呢?
事实上,这是一个错误,它的偏移量4超过了字符串的访问,就像你访问一个数组的元素,超出了索引范围一样,这样有可能会出大事!这个表达式的结果是一个不可预测的值。
什么时候会用到类似这些形式的表达式呢?
《C与指针》给出了一个神秘函数的例子:
#include <stdio.h>
void mystery( int n )
{
n += 5;
n /= 10;
printf("%s\n", "**********" + 10 - n );
}
最后一个标准输出语句使用了字符串常量,下面我们测试下这个函数执行的情况:
#include <stdio.h>
#define M 6
void mystery( int n )
{
n += 5;
n /= 10;
printf("%s\n", "**********" + 10 - n );
}
int main()
{
mystery( M );
return 0;
}
我们通过改变M的值,来运行这个程序:
大家可在这个网站上实验:https://www.tutorialspoint.com/compile_c_online.php
当输入M = 10 时候:
输入M = 100时:
各位自行总结规律!
各位大侠如果觉得这个例子垃圾,那我们就再看一个例子:
这个例子在递归函数中也见过,非常好玩!
贴出来代码:
//接受一个整型值(无符号),把它转换为字符并打印它。
#include <stdio.h>
void binary_to_ascii(unsigned int value)
{
unsigned int quotient;
quotient = value / 10;
if(quotient != 0)
binary_to_ascii(quotient);
putchar(value % 10 + '0');
}
这个例子,如果你不太了解递归函数,恐怕会感到无解!
但它确实能实现把一个整型值转换为字符打印的操作。
测试下呗:
//接受一个整型值(无符号),把它转换为字符并打印它。
#include <stdio.h>
void binary_to_ascii(unsigned int value)
{
unsigned int quotient;
quotient = value / 10;
if(quotient != 0)
binary_to_ascii(quotient);
putchar(value % 10 + '0');
}
int main()
{
binary_to_ascii(16);
return 0;
}
下面我们对这个例子进行修改,以十六进制的形式打印结果值:
//接受一个整型值(无符号),把它转换为字符并打印它。
#include <stdio.h>
void binary_to_ascii(unsigned int value)
{
unsigned int quotient;
quotient = value / 16;
if(quotient != 0)
binary_to_ascii(quotient);
putchar( "0123456789ABCDEF"[value % 16] );
}
int main()
{
binary_to_ascii(26);
return 0;
}
这就很完美了,成功的运用了字符串常量是一个指针常量的意义来设计程序!
当然,如果觉得字符串常量难以理解的话,可以有一个简单的替代方案,但是代码没有字符串常量简洁:
//接受一个整型值(无符号),把它转换为字符并打印它。
#include <stdio.h>
void binary_to_ascii(unsigned int value)
{
unsigned int quotient, remainder;
quotient = value / 16;
if(quotient != 0)
binary_to_ascii(quotient);
remainder = value % 16;
if( remainder < 10 )
putchar( remainder + '0' );
else
putchar( remainder - 10 + 'A' );
}
int main()
{
binary_to_ascii(26);
return 0;
}
【 C 】字符串常量的更多相关文章
- 使用Microsoft Roslyn提取C#和VB.NET源代码中的字符串常量
Microsoft Roslyn是微软.NET“编译器即服务(Compiler as a Service)”的主要产品,它提供了开放的编译器API,并为源代码产生.分析和重构提供了新一代的语言对象模型 ...
- Java字符串常量池
JVM为了减少字符串对象的重复创建,维护了一个特殊的内存,这段内存被称为字符串常量池. Java中字符串对象的创建有两种形式:一种是字面量形式,String str = "a":一 ...
- 字符数组,字符指针,字符串常量,以及sizeof的一些总结
1.以字符串形式出现的,编译器都会为该字符串自动添加一个\0作为结尾 如在代码中写"abc",编译器帮你存储的是"abc\0". 2.数组的类型是由该数组所存放 ...
- Java中的字符串常量池
ava中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid";,另一种就是使用new这种标准的构造对象的方法,如String str = new ...
- C++字符串常量
C++字符串常量 当一个字符串常量出现于表达式中时,它的值是个指针常量.编译器把这个指定字符的一份copy存储在内存的某个位置(全局区),并存储一个指向第一个字符的指针. #include <i ...
- PostgreSQL中美元符号引用的字符串常量
虽然用于指定字符串常量的标准语法通常都很方便,但是当字符串中包含了很多单引号或反斜线时很难理解它,因为每一个都需要被双写.要在这种情形下允许可读性更好的查询,PostgreSQL提供了另一种被称为“美 ...
- Python学习总结4:字符串常量与操作汇总
参考博客:http://www.cnblogs.com/Camilo/archive/2013/09/21/3332267.html http://www.cnblogs.com/SunWentao/ ...
- C++常量(C++数值常量、字符串常量、符号常量)
http://see.xidian.edu.cn/cpp/biancheng/view/104.html 字符串常量 用双撇号括起来的部分就是字符串常量,如"abc"," ...
- 字符串常量演示Demo
public class StringDemo { public static void main(String[] args) { // TODO Auto-generated method stu ...
- C语言中字符串常量到底存在哪了?
常量存储总结局部变量.静态局部变量.全局变量.全局静态变量.字符串常量以及动态申请的内存区 1.局部变量存储在栈中2.全局变量.静态变量(全局和局部静态变量)存储在静态存储区3.new申请的内存是在堆 ...
随机推荐
- 省钱小贴士(ECS):教你如何每年省出8w+ 块
随着用户越来越多地使用阿里云的ECS服务,如何用最小的成本来保有ECS,成为用户越来越重要的关注点. 变更点 为了更好的服务客户,ECS团队调整了系统盘的最小容量限制 linux系统 core os调 ...
- JAVA对象与内存控制
1.1 实例变量和类变量 成员变量和局部变量: 局部变量分为三大类: 1)形参:在方法签名中定义的局部变量,由方法调用者为其赋值,随方法的结束而消亡. 2)方法内的局部变量:在方法内定义的局部变量,随 ...
- iOS动画的逻辑结构:动画的定义--动画是采用连续播放静止图像的方法产生物体运动的效果。
动画的定义:视图+时间+空间+速度 视图信息的时空变换: 视图组的按时间逐帧展示: Core Animation 类的继承关系图 各类常用属性 CAMediaTiming:CALayer和Core A ...
- Django中模型(五)
Django中模型(五) 六.模型查询 1.概述 查询集,表示从数据库获取的对象集合. 过滤器就是一个函数,基于所给的参数限制查询集结果.查询集可以有多个过滤器. 从sql角度来说,查询集合等价于se ...
- 通过iframe标签绕过csp
iframe.php代码如下: allow-popups开启时,window.open就可以打开新的窗口. 看csp规则,默认是在当前域内,如果这是一个ctf题的话,就很简单了,window.loca ...
- 1、Spring Cloud - 微服务简介
前言: 业界大牛马丁.福勒(Martin Fowler) 这样描述微服务: 论文网址:https://martinfowler.com/articles/microservices.html 就目前而 ...
- Kali-linux使用Wifite破解无线网络
一些破解无线网络程序是使用Aircrack-ng工具集,并添加了一个图形界面或使用文本菜单的形式来破解无线网络.这使得用户使用它们更容易,而且不需要记住任何命令.本节将介绍使用命令行工具Wifite, ...
- 容器适配器(一):queue
除了标准的顺序容器外,STL还提供了3种容器适配器,queue,priority_queue和stack 适配器是对顺序容器的包装,它的作用是简化接口. queue接口十分的简单,只有8个方法.再加上 ...
- Ubuntu安装MySQL/MariaDB
安装MariaDB/MySQL MariaDB是MySQL的分支,与MySQL高度兼容,几乎所有的命令都一样.MariaDB是由前MySQL的开发人员离开Sun公司后开发的,目的是为了防止Oracle ...
- PL/SQL Developer修改窗口字体和大小
工具 → 首选项 → 字体 → 选择, 然后自己调节设置