C语言strcat函数举例带指针,由strcat函数引发的C语言中数组和指针问题的思考

问题一

首先,来看一下下面这段代码:

#include

#include

int main() {

char *str = "media";

char *tmp = "aaa";

printf("str: %s\n",str);

strcat(str,tmp);

printf("str: %s\n",str);

return 0;

}

代码打眼儿一看,功能很明显:把str指针指向的字符串和tmp指针指向的字符串连接起来再赋给str指向的字符串。我们把这个程序运行一下,如下图:

a265718ec79f7938a1100db15fcca13a.png

报出了段错误,使用cgdb调试一下,发现问题是出在strcat函数处:

e26277aac4697d6fbee1b1d6637569c6.png

感觉很奇怪,就去查找了strcat函数的一些示例,发现几乎所有的strcat的示例都是连接的两个数组类型字符串或者一个数组类型一个指针类型(指针类型指向的字符串一定是接在数组字符串之后)。自己手动测试了一下,把*str改为了str[20],发现程序成功运行:

683f7d0d78651ad5c00ef2f422de8d3e.png

后经过一系列的文档查阅,得知定义为指针所指向的字符串是常量字符串,只能读取不能写入。运行过程中,指针变量p所指向的内存是分配在堆中的,且只分配了足够其指向的内容的内存。将q连接到p后,自然p是没有其他空间给q了,所以发生了段错误。要连接这样的字符串,得另外开辟一个空间存放连接起来的字符串。如果非要将两个变量定义为指针类型,可以把程序修改为以下形式:

#include

#include

int main() {

char *str = "media";

char *tmp = "aaa";

char *res = (char *)malloc(strlen(str)+strlen(tmp)+1);

printf("str: %s\n",str);

strcat(strcpy(res,str),tmp);

printf("str: %s\n",res);

return 0;

}

得到的结果正确:

ec60aaba0b084f31a2b1c199bedb75fe.png

问题二

这学期上了一门课,需要在Linux C中完成一个项目。其中有一个功能模块是在指定文件夹目录下递归查找当前目录下的所有文件,并将所有的文件的路径存入一个数组中。其实递归查询当前文件目录下的所有文件这个功能并不难,网上也有很多实现方法。我所遇到的问题又出在了数组和指针的问题上(指针涉及的对内存的操作真的是C的最大难点。。),下面是问题具体描述:

我所要实现的功能是,在main的参数中指定了所要扫描的文件夹,在指定文件夹下扫描所有的文件,并把所扫描到的所有文件的路径存入一个数组中。我使用了dirent.h头文件中定义的结构体,当d_type == 8是文件,d_type == 4时是文件夹。等于4时便递归调用函数实现扫描文件夹下的所有文件,发现一个,printf一个。然后定义了一个全局的char数组指针path来指向所扫描到的文件路径,在main函数下输出path来验证路径是否正确的存入了数组。主要代码如下:

c58646640f4baff7c411d48f49340bc1.png

然后我所要扫描的文件夹file下有三个txt文件,分别是1.txt、2.txt、3.txt:

8c079a2b9865c915ba1a445bf174c332.png

在运行程序的时候,出现了问题:在执行readfilelist函数的时候,可以成功的发现并输出file文件夹下的三个txt文件,可是path中所存放所找到的文件路径似乎并不正确,数组中所有的值都相同,且都是最后一个所找到的文件的路径,如下图所示(path array has following data下面输出的路径是path数组指针中的数据):

302dc9d7e384f556da700db761dd8638.png

很奇怪,在readfilelist中printf一下每一次循环path中的值试试看吧,发现每一次循环输出的path中的值是正确的(如下图#后的输出结果)????????这就相当于,逐步输出path中的值是正确的,在main中重新for循环遍历一下结果就变了,path还是一个全局变量不存在生存期的问题。而且逐步输出的时候数组下标count都是及时++的,如果是递归返回时的问题,不可能下标已经是3了程序还能将数组退到0、1、2位置更改数组中的值吧。这也太奇怪了。。。。

9ce9bc8ad88f83316df044e0a6411005.png

这个结果只能有一种解释:在逐步将文件路径存入数组相应的位置时,数组所有的位置的值同时都被改变了。不过我还是不能理解为什么会发生这样的问题,立马打开cgdb。。

display一下path和局部变量ingpath(ingpath是普通字符数组类型,作用是当文件类型是文件时,将文件路径连接完整,再统一赋值给path),看看他俩的值和地址到底是怎么变化的。

第一次扫描到3.txt文件,将值存入path中,地址后四位为d5f0:

1d19844b0be91e34030d6bf4c1846931.png

继续执行,又找到了1.txt文件,在操作数组ingpath时出现了问题:还没有执行到给path赋值,只是在对ingpath进行修改操作时,path中的内容也发生了改变:

e555fa9f9a198ecda9f9af91f067da70.png

继续执行观察到给path赋值,发现确实和之前的猜想一样,逐步将文件路径存入数组相应的位置时,数组所有的位置的值同时都被改变了:

86f1c55406e28d88b586950b6af6b78b.png

并且,所有经过ingpath所给path赋的值的内存地址都是相同的,都是d5f0。至此,破案了:在将数组指针path的地址指向数组变量ingpath时,path就已经绑定ingpath的地址了(和C++11中的引用&用法有些类似),数组变量的内存地址不会发生改变,而且所有对于ingpath的操作也会相应的对path进行操作。path数组指针的每一位存入数据的内存地址都相同,自然所对应的数据就相同,进而path中所有的值都是相同的。

如何对此进行改进呢。我的想法是:把ingpath的类型也改为指针类型,作为局部变量,每一次循环开始时都重新为ingpath指针指向的常量空间重新malloc一下,这样就保证了ingpath指向的内存地址每一次循环都被重新分配而不会相同,进而“解除”了与path所指向内存地址的绑定。这样的话,对ingpath指向的地址中的值进行修改就不会影响到path指向的地址中的值,保证了ingpath顺利存入path的相应位置。

按照这个思路,对代码进行了修改:

d836ff5c14d9341cb177c830aa13ba22.png

果不其然,输出path,正确的输出了所有文件的路径:

425e2c39e090f43ac48407268c08d406.png

总结

一个小问题,只需要修改一行代码就解决了的问题折腾了一天时间(此处,真的想发送一个围笑_)。不过时间没有白折腾,基本搞清楚了指针和数组相关的问题,收获良多,还是很开心的。把这个debug的过程写出来作为一个分享。

最后,敲黑板:指针只是一个内存地址的引用,指向内存地址空间。如果在其他地方更变了这个地址空间里的数据,指针指向该地址空间中的值也会随之改变(废话,不都是一个值么)。

C语言中数组与指针的异同之处!你不知道的编程奥秘~

C语言的数组和指针一直是两个容易混淆的东西,当初在学习的时候,也许为了通过考试会对指针和数组的一些考点进行突击,但是很多极其细节的东西也许并不是那么清楚.本篇侧重点在于分析数组与指针的关系,什么时候数 ...

c语言中数组,指针数组,数组指针,二维数组指针

1.数组和指针 ] = {,,,,};// 定义数组 // 1. 指针和数组的关系 int * pa = array; pa = array; // p[0] == *(p+0) == array[0 ...

C/C++中数组与指针的关系探究

数组与指针 长期以来,在C/C++中,数组名和指向数组首元素的指针常量到底是以一种什么关系,一直困扰着很多人.很多地方,甚至是一些教科书中都在说,"数组名就是一个指向数组首元素的指针常量&q ...

c语言中数组相关问题

c语言中数组相关问题: 1.数组基本定义: 相同数据类型的元素按一定顺序排列的集合,就是把有限个类型相同的变量用一个名字命名,然后用编号区分他们的变量的集合,这个名字称为数组名,编号称为下标.组成数组 ...

对于C语言中数组名是指针的理解

我们都知道,c语言中数组名是一个指针,比如下面这段代码 #includeusing namespace std;int main(){ int a[4]={1,2,3, ...

C中 数组和指针的异同

数组在很多情况下是和指针等价的,数组的下标运算和指针的解引用也有等价形式:arr[i] == *(arr + 1):但是也有一些情况下数组和指针是不一样的:extern int arr[]; exte ...

《挑战30天C++入门极限》新手入门:C/C++中数组和指针类型的关系

新手入门:C/C++中数组和指针类型的关系 对于数组和多维数组的内容这里就不再讨论了,前面的教程有过说明,这里主要讲述的数组和指针类型的关系,通过对他们之间关系的了解可以更加深入的掌握数组和指 ...

别人不会给你说的---C语言中数组名和指针的区别 及 sizeof用法

引自: http://blog.csdn.net/tianyue168/article/details/5781924 #i nclude  int  main( ...

C++语言中数组指针和指针数组彻底分析

#################################                              ##       基本知识               ##        ...

随机推荐

解决mac升级后,出现的 xcrun: error: invalid active developer path, missing xcrun 错误

最近升级了mac系统,然后接着写代码就出问题了. 报错信息如下: xcrun: error: invalid active developer path (/Library/Developer/Com ...

如何解决div层被flash遮盖的问题

页面构建中的Flash层会遮挡Div的问题,一般通过设置wmode="transparent" 或wmode="window"就可以解决.不过对于Flash视频 ...

UML类图关系大全-转

1.关联 双向关联: C1-C2:指双方都知道对方的存在,都可以调用对方的公共属性和方法. 在GOF的设计模式书上是这样描述的:虽然在分析阶段这种关系是适用的,但我们觉得它对于描述设计模式内的类关系来 ...

发布网站,报Access to the path is denied的解决办法

错误: Server Error in '/' Application.---------------------------------------------------------------- ...

hdu2157矩阵快速幂

How many ways?? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

使用jsonp完美解决跨域问题

调用web接口,get请求,发现提示:No 'Access-Control-Allow-Origin' header is present on the requested resource. 这个和 ...

Linux Samba服务主配文件smb.conf中文详解【转】

转自:https://blog.csdn.net/maotianwang/article/details/52524732 从网上找到描述比较详细的smb.conf中文解释: 服务名:smb 配置目录 ...

Matlab练习——rpy2tr函数与自己实现的ZYX欧拉角的结果不同的问题

问题背景:在根据这本书的Z-Y-X欧拉角原理用Matlab实现旋转矩阵求解时,发现与直接调用机器人工具箱中的rpy2tr()函数得出的结果并不相同. 首先:先检查自己写的函数 ...

Storyboarding by Scripting

Storyboarding by Scripting In the .osu file, under [Events]:Note: underscores can be replaced with s ...

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值