Linux C函数,数组,指针,复杂声明

函数的递归调用
递归函数是指“自己调用自己”的函数,函数不可能不停的调用自己,所以递归函数一定具备结束条件
例一:
递归函数binary Search()实现二元搜索算法,在排序好的数组中找到特定元素。首先,该函数根据搜索条件比较数组中间的元素,相同就返回该元素指针,不同该函数调用自己,在可能的另一半数组中搜索,一直递归进行,直到找到符合条件的元素。如果数组剩下长度为0,则表示无符合条件的元素。

long* binarySearch(long val,long array[],int n){
	int m=n/2;
	if(n<=0){
		return NULL;
	}
	if(val==array[m]){
		return array+m;
	}
	if(val<array[m]){
		return binarySearch(val,array,m);
	}else{
		return binarySearch(val,array+m+1,n-m-1);
	}
}

对于有n个元素的数组来说,二元搜索算法最多执行 1+log2(n)次比较。

注意递归函数基于这样的事实:每次调用函数时,都会重新建立局部变量。这些变量和返回时的地址需要调用栈空间,所以要保证栈空间足够;

传参
调用函数时,如需要复制数据对象,则运行成本很高。而且,函数没有办法修改原始变量,只能修改原始变量的复制版本

typedef struct{
	int id;
	char* name;
	int age;
}Student;

void change(Student stu){
	stu.age = 50;
}
int main(){
	Student stu;
	stu.id=100;
	stu.name ="zhang";
	stu.age=20;
	printf("%d,%s,%d\n",stu.id,stu.name,stu.age);
	change(stu);
	printf("%d,%s,%d\n",stu.id,stu.name,stu.age);
}
运行结果:
100,zhang,20
100,zhang,20

然而,如果函数的参数时变量的地址,那么函数就可以通过指针,直接获取原始变量,并修改原始变量的值。所以,C中也提供了传址调用函数

typedef struct{
	int id;
	char* name;
	int age;
}Student;

void change(Student* stu){
	(*stu).age = 50;
}
int main(){
	Student stu;
	stu.id=100;
	stu.name ="zhang";
	stu.age=20;
	printf("%d,%s,%d\n",stu.id,stu.name,stu.age);
	change(&stu);
	printf("%d,%s,%d\n",stu.id,stu.name,stu.age);
}

运行结果:
100,zhang,20
100,zhang,50

数组初始化
int a[10]={1} //a[0]=1,其余都为0
数组地址
int* p=a;
x=a[i];
x=*p;
在功能上等价,性能上不同。前者为了确定a[i]的地址,需要将i与类型长度相乘,在和a[i]首地址相加;后者只需要简介引用指针p。

在这里插入图片描述
|表示形式 | 含义 | 地址值
|&a | 指向二维数组的指针 |1000
| a | 二维数组名,指向一维数组a[0],即第0行首地址 |1000
a[0],(a+0),a | 第0行第0列元素地址 |1000
a+1,&a[1] |第1行首地址 |1006
a[1],
(a+1) | 第1行第0列元素地址 |1006
a[1]+2,
(a+1)+2, &a[1][2]| 第1行第2列元素地址 |1010
(a[1]+2),(*(a+1)+2),a[1][2] |第1行第2列元素的值 |元素值为11

array_name和&array_name的区别
前者时指向数组中第一个元素的地址
后者是指向整个数组的地址

字符数组和字符串
在定义字符串变量时,需要有足以容纳该字符串的数组和指针,并且保证为NULL留出空间
问题一:
char a[12];
strcpy(a,“Hello, world”);
上例中,a只能容纳12个字符,而“hello,world”有13个字符(包含NULL),因此NULL字符会复制到a以外的位置可能会毁掉a四周内存空间的一些数据
例一:
char a[12]=“Hello, world”;
此时的a是一个字符数组而不是字符串所以不包含NULL;
更好的方法
char a[]=“Hello, world”
不设定数组长度编译器会自行计算所需要的空间;

strcmp源码分析

函数中的变量存储位置
int a=0; 初始化的全局变量,保存在数据段
char* p1 未初始化的全局变量,保存在BSS段,BSS通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。特点是:可读写的,在程序执行之前BSS段会自动清0。所以,未初始的全局变量在程序执行之前已经成0了。
int main(){
int b; 未初始化的局部变量,保存在栈上
char s[]=“abc”; ”abc“保存在常量区,数组保存在栈上,并将常量区的”abc\0"复制到该数组中。这个数组可以随意修改
char* p2; 未初始化的局部变量,保存在栈上
char* p3 =“123465”; p3保存在栈上,“123456\0"保存在data区的read_only部分
注意如果令p3[1]=9;则程序崩溃,指针可以访问但不允许改变常量区的内容
声明了一个指针p3并指向"123456\0“在静态区中的地址,事实上p3应该声明为char const*,以免可以通过p3[i]="…"可以去修改这个字符串的内容
如果做了,在常量区的系统中可能会导致异常。
static int c=0; 初始化的静态局部变量;保存在数据区
p1= (char*)malloc(sizeof(char)10);分配10字节区域保存在堆上
p1= (char
)malloc(sizeof(char)*20);分配20字节区域保存在堆上
strcpy(p1,“123456”);
return 0;
}

指针是变量
系统为指针分配内存空间
指针有自己的地址
指针存的值为地址
在64系统中,typeof(指针)=8,地址占8字节

常量指针和指针常量
当const在之前就是常量指针,在之后就是指针常量
const char* p 定义一个常量指针,指向一个常量,内容不可更改但指针本身可以修改
char *const p=a; 定义一个指针常量,指针是常量不可更改,但是指针指向的内容可以修改
char *p =“abc” 定义一个常量字符串,存储在静态存储区的常量存储区。值不可更改,但是指针可以修改

指针数组
typename *p[n] 定义一个数组,数组包含n个指针变量p[0],p[1]…

数组指针

typename  (*p)[n]  定义**一个**指向含n个数据元素的数组的指针
int main(){
	int arr[]={1,2,3,4,5,6};
	int (*p)[6];
	p=&arr;
	printf("%d", *(*p+3));
	printf("%d", *(*(p+1)-3));
}

函数指针

datatype (*fun)(参数列表)void*fun)(int *,int*);
把函数的地址赋给函数指针,通过指针调用函数
int (*pfun)(int*,int*);   定义函数指针
int fun()(int*,int*){}     定义函数
pfun=fun;                  指针赋值
(*pfun)(p,q);				 调用函数

指针函数
返回值为指针的函数
datatype* fun();

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值