char数组和char指针应该注意的

数组要么在静态区被创建(如全局数组),要么在栈上被创建。数组名对应着(而不是指向)一块内存,其地址与容量在生命周期内保持不变,只有数组的内容可以改变。

指针可以随时指向其他类型的内存块,它的特征是“可变”,所以常用指针来操纵动态内存。指针远比数组灵活,但也更危险。

 

1.返回指向栈上的内存的指针

char * testStr1(){
	char  value[4] = "hello";
	return value;
}
void main(){
       char *str = NULL;
       str = testStr1();//str的内容是垃圾
       cout<<str<<endl;
}

 

有问题,value的内存位于栈上,该内存在函数体结束时被自动销毁。所以,return语句不可返回指向“栈内存”的“指针”或“引用”。

但为什么以下两种形式可以呢? 

//1.返回int形栈上内存
int fun1()

{
    int j = 3;
    return j;

}

//类 Complex
//2.返回类(栈内存)
Complex fun2()
{
    Complex c;
    return c;
}

1)对于返回int型的栈上内存的解释:return返回值的机制为:将返回值存入eax寄存器中,然后系统再将eax中的值赋给变量(i)。

2)对于返回值是类类型的解释:返回值是对象时会调用拷贝构造函数。因为返回的局部变量在函数结束时已被销毁,所以编译器都会先建立一个此对象的临时拷贝,而在建立该临时拷贝时就会调用类的拷贝构造函数。

3)对于返回指向栈存储的“指针”的解释:

在执行return语句时,首先将return后面的地址值返回存入到比如eax寄存器中,然后系统再将eax中的地址值给接收函数返回地址的指针变量。这看起来都没什么问题,但问题在于两个方面:

[1]接收函数返回地址值的指针变量要访问此地址中的内容。

[2]子函数运行结束后,一切有关于局部变量的内存都已经释放回收。那么在用这个地址来操作就很危险:地址中没有内容

++++++++++++++++++++++++++++++++++++=

总结:

(1)return

不管是返回指针还是返回值,return将return之后的值存到eax寄存器中,回到父函数再将返回的值赋给变量。

(2)局部地址

在函数内返回一个指针会出错的原因:子函数运行完毕时,存局部变量的所有栈地址的内容已经被释放。若在父函数中再访问这些地址中的内容时,因为这些地址的内容已经被释放,所访问到的值可能是乱的、不定的。

参考:

1)http://www.cnblogs.com/wgang171412/p/5019148.htm return机制

2)https://blog.csdn.net/jmh1996/article/details/78384083 c/c++return如何实现的?return的内部机制

 

 

 

2.返回静态内存

char * testStr2(){
	char  * value = "hello";
	return value;
}
void main(){
       char *str = NULL;
       str = testStr1();
       cout<<str<<endl;
}

 

没问题,不会出错。只不过testStr2的设计概念是错的。因为testStr2内的字符串“hello”是常量字符串,位于静态存储区,它在程序生命周期内恒定不变,不允许改变。无论什么时候调用testStr2,它的返回值始终是同一个“只读”的内存块。

3.不能对空指针进行strcpy操作

char *testStr3(){
	char *value1 ="str";
	char *value2 = NULL;
	strcpy(value2 , value1);
	return value2;	
}

 

有问题,value2是空指针,没有分配内存。

 

 

4.参数为指针时,形参指向静态内存或者另一地址,实参实际上无任何变化

buf依然是空的,因为参数传递相当于是char *value = buf,value指向buf

而value = "hello",相当于是value指针指向了hello所在的静态内存,但是buf的内容没变

 void testStr4(char * value){
         value = "hello";
 }
void main(){
    char buf[16]={0};
    testStr4(buf);
}

 

5.buf最后是hello,参数传递,此时,value 和buf指向的是同一块内存,strcpy是将value1中的内容复制到value所指的内存中

返回时由于value和bufs还是指向同一块内存的,所以bufs的内容为hello.

void testStr5(char *value){
    char *value1 = "hello";
    strcpy(value, value1);
}
void main(){
    char buf[16]={0};
    testStr4(buf);
}

 

4和5要对比着看

6.如果函数的参数是一个指针,不要指望该指针去申请动态内存

void testStr6(char *p, int num){
    p = (char* )malloc(sizeof(char) * num);
}
void main(){
     char *str = NULL;
     testStr6(str, 100); //str仍为NULL
     strcpy(str, "hello");//运行错误
}

 

结合着4和3看。只是把p的内存地址变了,str丝毫未变。且每调用一次就会造成一次内存泄露,因为没有调用free释放内存。

如果非要用指针参数去申请内存,那么久应该该用“指向指针的指针”

void testStr7(char **p, int num){
     *p = (char* )malloc(sizeof(char) * num);
}
void main(){
     char *str = NULL;
     testStr6(&str, 100); //注意参数是&str,而不是str
     strcpy(str, "hello");
     cout<<str<<endl;
     free(str);
}

 

由于“指向指针的指针“这个概念不容易理解,可以用函数返回值来传递动态内存。

char * testStr8(int num){
     char *p = (char* )malloc(sizeof(char) * num);
     return p;
}
void main(){
    char *str = NULL;
    str = testStr8(100)
    strcpy(str, "hello");
    cout<<str<<endl;
    free(str);
}

 

用函数返回值来传递动态内存的方法需要特别注意一点,不要用return语句返回指向“栈内存”的指针,因为该内存在函数结束时自动消亡。(参考1)

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值