本文主要探讨指针,数组,字符串,函数
指针
int *p;
未绑定:*表示p为指针变量,占4字节
int a = 1;p = &a;
绑定:p与a地址绑定即p中存放a的地址
*p = *p +1;
解引用:p间接访问a的存储空间
左值与右值
int a = 1;
左值:变量对应的内存空间
右值:内存空间存储的数
野指针
野指针:指针变量定义时未初始化去解引用导致
避免野指针:
定义指针,初始化为NULL
指针解引用前,判断NULL
指针使用完,赋值为NULL
指针使用前,赋值绑定给可用地址空间
const与指针
const int *p; = int const *p;(*p为常量)
int * const p; (p为常量)
const int * const p;(p和*p为常量)
注意:const近谁修饰谁
注意:参数输入前加const,未加const参数是输出参数(默认)
数组
int a[5];
数组一次分配多个变量,变量在内存中存储依次相连(内存地址连续)
a是数组名,a不能做左值,a做右值表示数组首元素的首地址(&a[0])
a[0]表示数组首元素,做左值表示数组首元素的内存空间,做右值表示首元素的值
&a表示整个数组首地址,做右值表示数组首地址,不能为左值
&a是整个数组首地址,a是数组首元素地址,形式相同,意义不同
a和&a[0]做右值意义和数值相同
指针与数组
int *p;
int a[5];
p = a;
int (*q)[];
q = &a;
p+1;
p是 int *类型,&a是整个数组的指针,类型是int (*)[]
p+1表示p偏移1*sizeof(int)字节
指针与类型解析
所有类型数据都是以二进制的方式存储在内存中,int、char、short为整形,存储方式是相同,所占内存空间大小不同,float和double存储方式不同,与整形不同
int a = 5;a分配4字节,将5按int类型存储方式转成二进制存到对应内存空间中,printf打印a,printf内部的vsprintf按格式化字符串(%d)代表的类型解析a所对应的内存空间中的01序列
指针数据类型
int *p;p是变量本身,是int *类型,解析方式是地址解析。*p是指针指向的变量,是int类型。
char占1字节,int占4字节,int范围比char大,char的范围之内int和char可以相互解析,超过char范围后int解析char就会出错
sizeof和strlen
sizeof是计算变量或数据类型占用内存的字节数
strlen是计算字符串长度(不计入'\0','\0'为结束符
define和typedef定义指针类型
#define dpChar char *
typedef char *tpChar;
dpChar p1,p2; <==> char *p1,p2; <==> char *p1;char p2;
tpChar p3,p4; <==> char *p3;char *p4;
指针数组与数组指针
指针数组是数组,数组中存储指针变量
数组指针是指针,指针指向数组
int *p[5]; 指针数组
int (*p)[5]; 数组指针
int *(p[5]); 指针数组
函数指针与typedef
函数指针:void (*p)(); 类型是void (*)()
typedef定义数据类型,类型是数据模板,类型不占内存
注意:
typedef int* PINT;
const PINT p; <==> int *const p;
typedef int* PINT;
PINT const p; <==> int *const p;
typedef const int* CPINT;
CPINT p; <==> const int *p;
字符串与字符数组
字符串是指针指向头、固定尾部('\0')的地址的一段连续内存
char *p = "linux";p是字符指针,指向字符串起始地址
p是字符指针,占4字节,"linux"在代码段,5字节存储"linux",'\0'占1字节,共10个字节
字符数组char a[] = "linux";<==> char a[] = {'l', 'i', 'n', 'u', 'x', '\0'};占6字节
递归函数
内存:栈内存中执行递归,每次递归都需要消耗栈内存
收敛性:递归函数必须终止递归条件,栈内存耗尽之前递归收敛,否则栈溢出
main函数
main函数是整个程序的入口,返回值给父进程(0执行成功,负数执行失败),shell用$?打印执行结果
父进程给main函数传参,int main(int argc,char *argv[]);argc是参数个数,argv是字符串数组(实际参数)
demo1:
修改gcc编译器定义的const类型数据(部分编译器如此)
#include <stdio.h>int main()
{const int a = 10;int *p;p = &a;printf("before modify : a = %d\n",a);printf("before modify : *p = %d\n",*p);(*p)++;printf("after modify : a = %d\n",a);printf("after modify : *p = %d\n",*p);return 0;
}
demo2:
sizeof和strlen练习
#include <stdio.h>int main()
{char str[] = "hello"; printf("sizeof(str) = %d\n",sizeof(str)); printf("sizeof(str[0]) = %d\n",sizeof(str[0])); printf("strlen(str) = %d\n",strlen(str));char *p=str; printf("sizeof(p) = %d\n",sizeof(p)); printf("sizeof(*p) = %d\n",sizeof(*p)); printf("strlen(p) = %d\n",strlen(p)); int n=10; printf("sizeof(n) = %d\n",sizeof(n)); int b[100];printf("sizeof(b) = %d\n",sizeof(b));return 0;
}
结果示例:
demo3:
5的 阶乘
#include <stdio.h>int factorial(int num)
{if(num == 1){return 1;}else{return num * factorial(num-1);}
}int main()
{int result;result = factorial(5);printf("the factorial of 5 is %d\n",result);return 0;
}
结果示例:
递归内部剖析
#include <stdio.h>void factorial(int num)
{printf("before factorial :num = %d\n", num);if (num > 1){factorial(num-1);}else{printf("factorial end : num = %d\n", num);}printf("after factorial : num = %d\n", num);
}int main()
{factorial(3);return 0;
}
结果示例:
斐波那契数列
F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3)
#include <stdio.h>int func(int num)
{if(num == 1){return 1;}else if(num == 2){return 2;}else{return func(num-1)+func(num-2);}
}int main()
{int result;result = func(5);printf("the func of 5 is %d\n",result);return 0;
}
结果示例:
demo3:
main函数的返回值
#include <stdio.h>int main()
{return 27;
}
结果示例: