c语言 指针到字符串,C语言中的指针和字符串

前言

务必理解指针与内存模型,不要死记硬背。

内存里的字符串

C语言中的字符串一般是char *类型的,这是怎样存在内存中的呢?

cchar *s = "NIHAO";

| s:400 |

|---|---|---|---|

|'N'|'I'|'H'|'A'|'O'| 0 |

|---|---|---|---|---|---|

|400|401|402|403|404|405|

如是上图,假设字母A处于内存的第400号格子,那么后面几个字母也是紧跟着的。

变量s本身并没有储存字符串,而存的是字符串的首地址400。也即,s指向这个字符串。

为什么没有专门一个字符串的类型而是要靠一个指针指向它呢?因为字符串的长度是不固定的,所以一个字符串还包含着长度信息,基本类型是无法处理数据结构的。

我们都知道字符串是以0结尾的,而且这个更像是一种约定,C编译器本身并没有对此做任何保证。比如这样

cchar s[3] = "asd";

puts(s); /* prints "asd" or something longer */

这样做是危险的,因为s只有3个格子,字符串结尾的0并没有放进去。如果在它后面的内存格子并不是0,那打印这个字符串时就跟我们预期的不一样了。

字符串常量不可写

c"abc"[0] = 'z'; /* wrong */

char *s = "abc";

s[0] = 'z'; /* wrong */

char s[5] = "abc";

s[0] = 'z' /* right */

当指针s指向的是字符串常量(即直接写在程序里面的字符串时),要注意它是不可写的

为啥用数组就没问题呢,因为数组的初始化和指针有点区别

cchar s[5] = "abc";

/* 相当于 */

char s[5];

strcpy(s, "abc");

如果担心自己会不小心写错,可以加上const关键字,这样编译的时候就会报错

这是一个好习惯,接下来的示例程序中都会这么写。

cconst char *s = "abc";

s[0] = 'z'; /* causes a compiling error instead of runtime error */

指针是要初始化才能使用的

c/* wrong */

char *s;

s[0];

上面的程序编译是能过的(可能有warning),但运行是一定会出错的,因为编译器并不知道s指向哪些格子。

c/* right */

const char *s = "NIHAO";

s[0];

这样,其实是隐式的分配了6个格子(包括字符串结尾的0),并让s指向它们

c/* right */

char s[6];

s[0];

c/* right */

char s[6] = "NIHAO";

s[0];

数组其实跟指针没什么区别,主要的区别是它在声明的时候就分配好了格子(方括号里的6就是告诉编译器给我6个格子),而且数组不能改变它的指向(也不能再要更多的格子)。

为什么不能用等号来比较字符串?

比较字符串

cconst char *s = "abcd";

const char *t = "abcd";

/* wrong */

if (s == t) {

...

}

/* right */

if (!strcmp(s, t)) {

...

}

因为s和t都没有存字符串的内容,它们存的是字符串的地址,如果用==比较,比较的是两个字符串的地址是否相同。我们希望比较的是内容是否相同。

请使用C语言库函数中的strcmp比较字符串是否相等

复制字符串

c/* tries to copy a string */

char s[5] = "abcd";

char *t = s;

t[3] = 'z';

puts(s); /* puts "abcz" */

上面这种做法让t和s指向同一字符串,修改t指向的内容,会发现s指向的内容也被修改了。这种做法没有错,经常会用到,但不一定是你想要的。

c/* wrong */

char *s = "abcd";

char *t; /* not initialized */

strcpy(t, s);

c/* right */

char *s = "abcd";

char t[10] = {0}; /* or char *t = (char *) malloc(5*sizeof(char)); */

strcpy(t, s);

使用strcpy复制字符串的内容而不是指针,但也要注意初始化t这个指针

怎样让函数得到一个字符串结果

int,float之类的很简单直接return就好

但现在我想写一个函数,它能够得到一个字符串

三种错误的或者不太好的做法

c/* no problem, but meaningless */

const char *f()

{

const char *s = "abcd";

return s;

}

/* wrong */

char *f()

{

char s[100];

/* do something with s */

return s;

}

/* result correct but not good */

char *f()

{

int n = 10;

char *s = (char *) malloc(n*sizeof(char));

/* do something with s */

return s;

}

第一种情况就不说了,返回一个字符串常量并没有问题因为它不可修改,但是不可修改也就没什么意义了。

第二种情况是完全错误的,返回一个局部的数组。这个数组的内存会在函数调用完后被收回,因此返回的指针指向的时候没有意义的地方。现代编译器一般都会对这个有warning。

第三种情况是返回malloc的指针。这种情况你可以得到正确的答案,但是不推荐,调用这个函数的人很有可能

不知道函数里面分配过内存

不知道应该什么时候free这部分内存

忘了free这部分内存

一旦没有注意,多次调用这个函数,结果就是内存溢出,这样的错误还非常不好排查,所以不推荐

正确的做法

正确的做法是把分配内存这种事情放在函数外面做,正如strcpy一样

cchar *strcpy(char *dest, const char *src)

{

int i;

for (i = 0; i < strlen(src); i++) {

dest[i] = src[i];

}

return dest;

}

dest是我们想要返回的字符串,它是从外面传进来的原因是我们不想在函数内部为它分配内存,而是在外面分配好了,里面只对这个字符串进行修改。

注意这里返回了char *但其实返回的正是原本传进来的dest,这里只是为了方便而已。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/359226.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【APICloud系列|33】移动应用软件加固步骤,适合所有的安卓应用市场

在腾讯开放平台下载应用加固工具legutools 下载安装打开 点击获取API密钥。链接: https://cloud.tencent.com/developer/article/1385239 一、登录腾讯云账号

Openjudge-计算概论(A)-放苹果

描述&#xff1a; 把M个同样的苹果放在N个同样的盘子里&#xff0c;允许有的盘子空着不放&#xff0c;问共有多少种不同的分法&#xff1f;&#xff08;用K表示&#xff09;5&#xff0c;1&#xff0c;1和1&#xff0c;5&#xff0c;1 是同一种分法。输入第一行是测试数据的数目…

c语言程序设计徐立辉答案,C语言程序设计 牛志成,徐立辉,刘冬莉著 清华大学出版社 9787302165620...

商品描述&#xff1a;【图书描述】:本书以2008年等级考试新需求为出发点&#xff0c;教学环境升级到了VC6&#xff0e;0平台。特别着重解决当前C语言教学中存在的一些问题和矛盾&#xff0c;在教学内容体系改革、教学过程组织、应对等级考试需要和素质教学实施等多个方面进行了…

怎么把图片内存变小尺寸保持不变呢。

在好多应用平台要求尺寸多少*多少&#xff0c;大小<50kb. 缩小图片的内存占用&#xff0c;但尺寸即分辨率不变&#xff0c;可以改变压缩的质量来实现。下面以PS为例&#xff1a; 1、用PS打开图片&#xff0c;然后选择文件菜单里的存储为&#xff0c;格式选择png。 2、选择…

C#vs Java哪一个更快? 将25k C#转换为Java(2)

在上一篇文章中&#xff0c;我描述了如何将25k行C&#xff03;转换为Java以及从该练习中学到的教训。 我收到以下问题&#xff1a; 顺便说一句很棒的文章。 迁移代码后&#xff0c;性能与C&#xff03;版本相比如何&#xff1f; 改写系统的动机之一是使系统变得更快&#xff…

将 改为c语言表达式,基于c语言表达式求解课程设计修改.doc

基于c语言表达式求解课程设计修改摘 要通过数据结构这门课程&#xff0c;我们较深入的了解到了栈&#xff0c;栈是一种重要的线性结构&#xff0c;它广泛应用于各种软件系统中&#xff0c;因此在面向对象的程序设计中&#xff0c;它们是多型数据类型。本次试验我们将探索表达式…

【Java必备资料包】

适合所有大厂java开发工场师。 链接&#xff1a;https://pan.baidu.com/s/1wRxRDCGvex_G2aCZ6W57vw 提取码&#xff1a;e9xu

SaaS系列介绍之十一: SaaS商业模式分析

1 配置模式 中国企业很多是人治&#xff0c;管理弹性非常大&#xff0c;公司的政策经常变化&#xff0c;管理流程、业务变化也非常大&#xff0c;发展也非常快;一个公司今年是10个人&#xff0c;明年是100个人&#xff0c;后年可能是1000人。管理机制、方法处于经常变化的状态&…

真机x86 android分辨率,Android-x86入门之--启动参数设置

之前的文章里面我也有提到分辨率的设置&#xff0c;这里就详细说下。Android-x86启动的时候有四个选项&#xff0c;大家都知道&#xff0c;第一个是高密度&#xff0c;第二个是低密度&#xff0c;两个启动之后的效果是不一样的&#xff0c;一个图标大&#xff0c;一个小&#x…

【APICloud系列|32】iOS 上架去除Icon图像中的alpha通道或透明度

上架的时候你们有没有遇到过这个问题?? 打开图片的“显示简介”,你会发现有个叫“alpha通道”的东西,(如果是“是”你的图片就不能上架)如下图: 第一种方法 怎样解决。把你的图片用PS打开,如下图选择进行操作:

关于excel中的查找

弹出查找界面后&#xff0c;点击“选项”按钮 在范围下拉框中选择&#xff1a; 1、工作表&#xff1a;表示在当前表sheet中进行查找 2、工作簿&#xff1a;表示在此excel整个文件中进行查找转载于:https://www.cnblogs.com/tonglingliangyong/p/4301873.html

android低电量提示,Android4.4开发之电池低电量告警提示原理与实现方法分析

本文实例讲述了Android4.4电池低电量告警提示原理与实现方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;之前版本的电池电量低是通过发送 intent ACTION_BATTERY_LOW来实现的&#xff0c;而在android4.4中&#xff0c;通过发送intent ACTION_BATTERY_CHANGED&…

网站如何快速搭建即时响应客服系统

首先简单说明一下情况&#xff0c;公司原来的网站是用微起点快速建站做的&#xff0c;几天就搭建完成啦&#xff0c;最近又原生开发了一个大数据网站。 自己在原来的网站搭建了一个客服系统&#xff0c;后来老板不喜欢&#xff0c;我又给取消啦。 直入主题啦 登录百度账号 选…

在NetBeans,Eclipse,IntelliJ,OpenShift和Maven上使用WildFly 9

WildFly 9 CR1是最近发布的。 包括许多很酷的功能&#xff1a; 智能负载均衡 HTTP / 2和SPDY支持 新的离线CLI模式 正常关闭单节点 新的仅Servlet发行版 而且这超出了通常的Java EE 7兼容性&#xff01; 该博客是一个快速检查&#xff0c;以验证它是否可以在所有三个主要…

【CSS】font样式简写(转)- 不是很建议简写

一、字体属性主要包括下面几个 font-family&#xff0c;font-style&#xff0c;font-variant&#xff0c;font-weight&#xff0c;font-size&#xff0c;fontfont-family&#xff08;字体族&#xff09;: “Arial”、“Times New Roman”、“宋体”、“黑体”等;font-style&…

Spring boot的简单用法

打算通过写一系列的文章,让大家能够认识SpringBoot,通过对SpringBoot的入门学习后,在通过一个示例Demo来让大家能够真正上手SpringBoot。 适合人群: 1、有一定Java基础的朋友 2、适合初中级的朋友。 1.什么是Spring Boot 来源官方文档: Spring Boot makes it…

android 布局防抖动,Android全屏返回布局抖动问题

在api19以后actvityA切到actvityB &#xff0c;如果B是全屏的&#xff0c;A是非全屏的&#xff0c;这个时候切换回A会有一个状态栏出现的动画&#xff0c;随着状态栏出现动画我们的布局会出现一个从上往下的抖动。在ActvityA的setContentView()方法后调用initStatusBar()方可解…

Bluetooth LE(低功耗蓝牙) - 第一部分

前言 在写这篇文章的时候&#xff0c;谷歌刚刚发布了Android Wear &#xff0c;摩托罗拉也发布了 Moto 360 智能手表。Android Wear的API还是相当基本的&#xff0c;是很好的文档材料&#xff0c;而且还会不断的更新&#xff0c;所以我不打算写一个关于他们的教程&#xff08;至…

Android查看web日志,详解Android WebView监听console错误信息

根据需求&#xff0c;我们要拿到h5的错误信息&#xff0c;并将error信息进行上报。查询了下Android WebView的API发现了WebChromeClient这个方法可以满足要求&#xff1a;Overridepublic boolean onConsoleMessage(ConsoleMessage consoleMessage) {//获取log的级别switch (con…