当一个字符串常量出现在表达式中时,它的值是个指针常量。编译器把这些指定字符的一份拷贝存储在内存的某个位置,并存储一个指向第一个字符的指针。但是,当数组名用于表达式中时,它们的值也是个指针常量。我们可以对它们进行下标引用、间接访问以及指针运算。

这些操作对于字符串常量是不是也有意义呢?

看看下面这个表达式是什么意思?

"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时:

各位自行总结规律!
各位大侠如果觉得这个例子垃圾,那我们就再看一个例子:

这个例子在递归函数中也见过,非常好玩!

【 C 】深入了解递归

贴出来代码:

//接受一个整型值(无符号),把它转换为字符并打印它。

#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 】字符串常量的更多相关文章

  1. 使用Microsoft Roslyn提取C#和VB.NET源代码中的字符串常量

    Microsoft Roslyn是微软.NET“编译器即服务(Compiler as a Service)”的主要产品,它提供了开放的编译器API,并为源代码产生.分析和重构提供了新一代的语言对象模型 ...

  2. Java字符串常量池

    JVM为了减少字符串对象的重复创建,维护了一个特殊的内存,这段内存被称为字符串常量池. Java中字符串对象的创建有两种形式:一种是字面量形式,String str = "a":一 ...

  3. 字符数组,字符指针,字符串常量,以及sizeof的一些总结

    1.以字符串形式出现的,编译器都会为该字符串自动添加一个\0作为结尾 如在代码中写"abc",编译器帮你存储的是"abc\0". 2.数组的类型是由该数组所存放 ...

  4. Java中的字符串常量池

    ava中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid";,另一种就是使用new这种标准的构造对象的方法,如String str = new ...

  5. C++字符串常量

    C++字符串常量 当一个字符串常量出现于表达式中时,它的值是个指针常量.编译器把这个指定字符的一份copy存储在内存的某个位置(全局区),并存储一个指向第一个字符的指针. #include <i ...

  6. PostgreSQL中美元符号引用的字符串常量

    虽然用于指定字符串常量的标准语法通常都很方便,但是当字符串中包含了很多单引号或反斜线时很难理解它,因为每一个都需要被双写.要在这种情形下允许可读性更好的查询,PostgreSQL提供了另一种被称为“美 ...

  7. Python学习总结4:字符串常量与操作汇总

    参考博客:http://www.cnblogs.com/Camilo/archive/2013/09/21/3332267.html http://www.cnblogs.com/SunWentao/ ...

  8. C++常量(C++数值常量、字符串常量、符号常量)

    http://see.xidian.edu.cn/cpp/biancheng/view/104.html 字符串常量 用双撇号括起来的部分就是字符串常量,如"abc"," ...

  9. 字符串常量演示Demo

    public class StringDemo { public static void main(String[] args) { // TODO Auto-generated method stu ...

  10. C语言中字符串常量到底存在哪了?

    常量存储总结局部变量.静态局部变量.全局变量.全局静态变量.字符串常量以及动态申请的内存区 1.局部变量存储在栈中2.全局变量.静态变量(全局和局部静态变量)存储在静态存储区3.new申请的内存是在堆 ...

随机推荐

  1. HTML学习---HTML状态码

    301 Moved Permanently 永久移动.请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI.今后任何新的请求都应使用新的URI代替302 Found ...

  2. H5 签到功能

    Introduce(介绍) 用户签到的H5例子(css+jquery,无图片),由于网上找的的用户签到例子都不好,要不就是好多图片组成的,要不就大量冗余代码,所以特意做了个签到界面(移动端). Use ...

  3. UML实践

    UML图一览 1.分工泳道图 使工作内容更加清晰 2.类图 更加细化了一些函数,对于之后的接口文档细节问题进行了约束 3.用例图 实现了一个玩家的整体可操作的概况 4.活动图 1)注册活动图 用于登录 ...

  4. ARM汇编之MOV指令

    http://blog.csdn.net/lsywk/article/details/8799837 一.指令格式 MOV{条件}{S}  目的寄存器,源操作数 二.指令详解 MOV指令可完成从另一个 ...

  5. 2424. [HAOI2010]订货【费用流】

    Description 某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初的库存量为零,第n月月底的库存量也为 ...

  6. gluoncv voc_detection

    https://github.com/zhreshold/gluon-cv/commit/73b3986aaa2e0d0e6f3f428c12072e3a9d29905e gluoncv可能版本还没更 ...

  7. appium 环境安装windows

    创建AVD -c  --sdcard  : 指向一个共享的SD存储卡的路径,或者是新的SD储存卡容量大小. -n  --name    : AVD的名字(该项是必须的) -a  --snapshot ...

  8. shell一次性执行多条命令

    1.每个命令之间用;隔开说明:各命令的执行给果,不会影响其它命令的执行.换句话说,各个命令都会执行,但不保证每个命令都执行成功. 2.每个命令之间用&&隔开说明:若前面的命令执行成功, ...

  9. TCP连接三次握手协议,释放连接四次挥手,以及使用 awl伪造mac地址进行多线程syn洪泛攻击。

    这个TCP连接就是一次追女生-谈恋爱-分手,追求比分手简单,但是分手比追求复杂.哥,谈了半年的女朋友,在就快要成功了的时候分了,原因是因为有人在后面该老子背后搞SYN洪泛攻击,最后女朋友丢失了.学会T ...

  10. 提交json串格式的POST请求

    提交json串格式的POST请求 Action() { web_reg_save_param("retCode", "LB=retCode\":\"& ...