c语言 char* 和char[]的返回值

文章讲述了char*和char[]在函数返回值中的差异,解释了name1报错的原因,介绍了使用static关键字处理局部变量以及malloc进行动态内存分配的方法。


正确计算c字符串的长度

char* 和char[]的返回值报错的原因

#include<stdio.h>
#include<stdlib.h>

char * fun(){
	char name1[]="cch";//改为char *name2="cch";不会报错
	return name1;//return name2;
}

int main(){
	fun();
	return 0;
}
# 编译结果显示如下:
[cch@aubin s]$ gcc file.c
file.c: 在函数‘fun’中:
file.c:6:2: 警告:函数返回局部变量的地址 [-Wreturn-local-addr]
  return name;

为什么name1会出现报错,但是name2不会出现报错

  • name1是fun函数内的局部变量,局部变量会保存在中,随着fun函数的结束,其地址会被释放,所以name1返回的是无效地址;但是name2是保存在常量区的,在fun函数结束后,常量数据不会消亡,它会直到整个程序结束才消失,所以name2返回的是一个有效的地址。

解决方法

static关键字

怎么避免以上的问题,可以使用static关键字

  • static全局变量只能声明后再本文中调用
  • static局部变量只能声明后再本函数调用

静态一直存在

  • static全局变量生命周期到程序结束
  • static局部变量生命周期到程序结束

静态全局变量

使用:在全局变量前加static关键字,修饰全局变量为静态全局变量

作用:改变全局变量的可见性:静态全局变量的存储位置在静态存储区,未被初始化的静态全局变量会被自动初始化为0。静态全局变量在声明他的文件之外的其他文件是不可见的,仅从定义变量的开始位置到文件结尾可见。

静态局部变量

使用:在局部变量前加static关键字,修饰局部变量为静态局部变量

作用:改变局部变量的销毁期:静态局部变量的作用域与局部变量的作用域是一样的,都是当定义这个局部变量的那个函数或者语句块结束时候作用域结束。但是不同的是,静态局部变量存储在静态存储区,当静态局部变量离开作用域后,并没有被销毁当该函数再次被调用的时候,该变量的值为上帝函数调用结束时的值

静态函数:

  • 使用:在函数返回类型前面加上static,修饰函数为静态函数
  • 作用:改变函数的可见性,函数的定义和声明在默认情况下都是extern的,但是静态函数只在声明他的文件中可见,不被其他的文件可见
#include<stdio.h>
#include<stdlib.h>

char * fun(){
	static char name1[]="cch";//改为char *name2="cch";不会报错
	return name1;
}

int main(){
	fun();
	return 0;
}

以上代码是可以正确运行的,因为name1为静态局部变量,虽然fun函数结束后其作用域消失,但是其name1存储在静态存储区,并没有随着作用域一起消亡,所以返回的是一个有效的地址。

malloc动态分配内存

malloc分配的内存是在上而不是在栈内存上的,所以可以使用动态分配内存的方式来解决问题。

#include<stdio.h>
#include<stdlib.h>

char * fun(){
	char *name1=(char *)malloc(10*sizeof(char));
	name1="cch";
	printf("%s\n",name1);
	return name1;
}

int main(){
	fun();
	return 0;
}

值得注意的是:char[]类型可以直接给char *类型赋值;但是反过来,char *类型不能给char[]类型赋值,如果非要赋值,可以使用strcpy函数

### C语言 `char**` 类型的意义 在C语言中,`char**` 是一种双重指针类型。它的意义可以从以下几个方面来解释: #### 1. 基本概念 `char*` 表示一个指向字符 (`char`) 的单层指针,而 `char**` 则表示一个指向 `char*` 类型的指针。换句话说,`char**` 是一个指向另一个指针的指针[^2]。 #### 2. 数据存储模型 假设有一个字符串数组如下所示: ```c char str_array[][10] = {"hello", "world"}; ``` 如果要创建一个可以动态访问这些字符串的机制,则可以通过 `char**` 来实现。例如: ```c char *str_pointers[] = {"hello", "world"}; // 数组中的每个元素都是 char* char **double_pointer = str_pointers; printf("%s\n", double_pointer[0]); // 输出 hello printf("%s\n", double_pointer[1]); // 输出 world ``` 在这里,`str_pointers` 是一个指针数组,其中每一个元素是一个指向字符串常量的指针(即 `char*`),因此可以用 `char**` 来引用这个数组[^5]。 #### 3. 动态内存分配场景 在涉及动态内存管理的情况下,`char**` 经常用作接收函数返回值或者传递参数的形式。例如,在使用 `malloc()` 函数时,可能需要将一块新分配的内存地址赋给某个指针变量。下面的例子展示了如何利用 `char**` 进行动态分配并修改外部指针的内容: ```c void allocate_string(char **output_str) { char a = 'A'; *output_str = &a; // 让 output_str 所指向的位置保存新的地址 } int main() { char *ptr_to_char = NULL; allocate_string(&ptr_to_char); printf("Allocated character is %c.\n", *ptr_to_char); // 输出 A } ``` 上述代码片段说明了 `char**` 如何用于间接更改原始指针所指向的对象[^4]。 #### 4. 结构体内嵌套应用实例 考虑更复杂的实际应用场景——结构体成员作为指针的情况。比如有这样一个例子展示如何操作包含指针字段的结构体对象: ```c #include <stdio.h> struct Record { char name[20]; }; void modify_name(struct Record **record_ptr){ strcpy((*record_ptr)->name,"Modified Name"); } int main(){ struct Record r={"Original Name"}; struct Record *rp=&r; modify_name(&rp); printf("Record's new name:%s\n",r.name); return 0; } ``` 此程序段里定义了一个名为 `modify_name` 的辅助方法接受的是指向记录类型的二级指针参数以便能够真正影响到调用者那里的原生数据副本而不是局部拷贝版本[^3]。 --- ### 总结 综上所述,`char**` 主要是用来处理多级间接寻址需求的一种工具;既可以简化对于复杂数据集合的操作流程又能在某些特定场合下提供必要的灵活性支持诸如链表节点链接维护等功能扩展可能性等等[^1].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值