C语言指针总结

1.指针基础定义和使用

char val='a';
char*p=&val;  //定义指针指向val
char**q=&p;

char*pa,pb;  //pa是char*,pb是char
char*pa,*pb;  //pa,pb都是char*

typedef char* PChar;
PChar pa,pb; //pa,pb都是char*

#define PCHAR char*
PCHAR pa,pb;  //值替换  char*pa,pb;

2.指针与const的结合

const int a=10;
int b=20;
//定义p指向a
const int *p=&a; //p具有常性
//p指向的值具有常性

int *const q=&a; //权限缩小 正确
//q具有常性

3.野指针和空指针

//野指针-悬挂指针-空悬指针
//所指地址不明确  随机地址:地址对应值没有访问权限
int *p; //野指针
*p=1;  //崩

//空指针 NULL     #define NULL 0
int *p=NULL;  //0号地址空间不具有访问权限
              //(内存前128M禁止访问)
*p=1; //崩

int *p=200000;//错误 类型错误 200000-->int
int *p=(int*)200000;//不建议  不安全
//*p崩

4.指针运算

4.1指针加整型

int val=10;
int *p=&val;  //*p解析4B空间
//*p解析的内存大小 取决于*p的类型
char num='a';
char *pn=#
*pn -- 解析1字节内存空间    *pn类型

4.2指针+n/-n

p+1能力  指针偏移量 从p所指地址开始向高地址偏移1

p-1能力                                                    低地址偏移1

指向1*sizeof(*p)位置  类型不变      p+1的类型: int *

基于连续地址空间 谈论指针相减

p与q之间相差的元素数量  p-q

4.3指针++/--

int arr[] = {1,2,3,4,5,6,7,8,9,10};
int *p = arr+2;   开始时指向arr[2] -- 3
*p++   --> 3      先解引用,表达式的值为3   后P的指针指向加一,指向arr[3]
*++p   --> 5      p先自增,后解引用 -- 5
++(*p) --> 6      ++ --> 自增操作,P指向的值不变,将arr[4]的值自增1
(*p)++ --> arr[4] = arr[4]+1  先解引用,在自增 
*--p   --> arr[3]:4
--*p   --> arr[3] = arr[3] - 1  --> 3

4.4数据在内存中的存储方式(面试题)

int val = 0x12345678
存储模式: 
大端模式(大端字节序): 高位数据存储低地址位置(高低/低高)
低地址                高地址
0x12 0x34 0x56 0x78  --- > 0x12345678
小端模式(小端字节系): 低地址位置存储低位数据(低低/高高) 
低地址                高地址
0x78 0x56 0x34 0x12 // ---> 0x12345678

大端模式,指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。

小端模式,指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。

验证大小端模式:、

 int val = 0x12345678;
 char* p = (char*)&val;  //  *p --> 0x12345678
 if(*p == 0x78) 小 
else   大端

5.指针数组

是一个数组,每个元素值类型 地址-->指针数组

int a,b,c;
int *pa=&a,*pb=&b,*pc=&c;
int *arr[]={&a,&b,&c};
const char* srr[]={"hello","abc","def"};

char str[]="hello";  //字符数组储存 hello
//字符串常量-->“hello”不许被修改
const char sub1[]="hello";//字符数组储存hello 不允许被修改
const char sub2[]="hello";
//sub1与sub2值相同  都不能修改  内存浪费

//修正
const char* p="hello";//字符串常量“hello”-->内存 数据区 .data
const char* q="hello";
//p,q分别开辟4B(x86)空间 保存数据区内hello的地址,常量在数据区只储存一份
//p,q在同一地址取值

6.数组指针

是一个指针,指向数组类型的指针

int arr[10];
int (*p)[10]=&arr;  //p的类型-->指针 int (*)[10]
//p+1--> 偏移量 1*sizeof(*p)B-->40B

int *q=arr;//q的类型-->指针 int*
//q+1--> 偏移量 1*sizeof(*q)-->4B

7.void*无类型指针

int *q=&val;//q+1偏移量4B
void* p;//储存地址 p+1-->无法知道偏移量 void所占字节数

void* 变量名=任意类型地址

注意:

1.不能对void*指针进行算数运算

2.void* p=#不能对void*指针进行解引用

通用操作:

1.void* arr  无类型指针 目的 储存地址 摒弃原生类型

2.const void* brr 遍历

3.逐字节拷贝

8.指针与函数

8.1返回值是指针

局部变量不允许被返回
int *Operate(int a,int b)//局部变量地址禁止返回
{
   int arr[]={a+b,a*b};
   // 普通局部生存周期函数调用结束销毁
   return arr;
}
//err
 
修改:
1.将 arr 设计为全局变量 所有函数共用一份该变量
int arr[2];
void Operate(int a,int b)//局部变量地址禁止返回
{
    arr[0]=a+b;
    arr[1]=a*b;
}
//全局变量 所有函数都可以访问并使用
 
 
2.修改为  静态局部变量 ----> 变量存活时间main函数结束时(项目结束)该变量内存才会被回收。
  存储区域:数据区.data
int *Operate(int a,int b)
{
  static int arr[]={a+b,a*b};//可见性在局部
    return arr;
}
延长局部变量生存周期 该局部变量前加static
静态局部变量:只被定义一次

8,2形参是指针

8.2.1 形参修改影响实参 必须传递实参的地址,解引用

void ChangeSize(int* psize)  psize[0x123]
{
  (*pisze)++;
}
int main()
{
 int size=10; size 0x123[10]
 ChangeSize(&size);
 return 0;
}

8.2.2节省空间

void Show(const int*arr,int len){}
 
void mystrcpy(char*sub,const char*str);

8.3函数指针

int add(int a,int b){}
int mul(int a,int b){}
函数返回值类型 (*p)(形参列表)=函数地址;
函数名:函数入口地址
int (*p)(int,int)=add;
p=mul;
 
//add(1,2);   p(1,2)
 
练习:
long*fun1();
定义指针 指向fun1并完成函数调用
long *(*p1)()=fun1;
p1(); 调用fun1函数;
 
void (*signal(int sig, void (*func)(int)))(int);
typedef void (*PFun)(int);
PFun signal(int sig,PFun pfun);
调用:
void func1(int a){如何复制操作 }
void func2(int b){ 如何粘贴操作 }
signal(CTRLC, func1);
signal(CTRLV,func2);

9.str系列函数

9.1.strlen

求字符串长度,返回‘\0’前的字符个数(不含‘\0’)

unsigned int mystrlen(char* str) {
	int len = 0;
	for (int i = 0; str[i] != '\0'; i++) {
		len++;
	}
	return len;
}
//size_t mystrlen1(const char* str)
//{
//	size_t count = 0;
//	while (*str != '\0')
//	{
//		count++;
//		str++;
//	}
//	return count;
//}

9.2. strcpy(char*arr, const char *brr)

将src指向的字符串复制到dest,需保证dest空间足够,会复制'\0'。

void mystrcpy(char* str, char* sub) {
	int j = 0;
	for (int i = 0; sub[i] != '\0'; i++) {//while(str[j]=sub[i]{
		str[j++] = sub[i];                //i++; j++;	}
	}
	str[j] = '\0';
}
void mystrcpy1(char* str, const char* sub)
{
	while (*sub != '\0') {
		*str = *sub;
		str++;
		sub++;
	}
	*str = '\0';
}
void mystrcpy2(char* str, const char* sub)
{
	while (*str = *sub) {//[hello\0]           sub hello
		str++;
		sub++;
	}
}

9.3. strcat(char *arr, const char *brr)

将src指向的字符串追加到dest末尾,dest需有足够空间,会合并'\0'。

void mystrcat(char* str, char* sub) {
	int len1 = mystrlen(str);
	int len2 = mystrlen(sub);
	int j = 0, i = 0;
	for (i = len1; i < len1 + len2; i++) {
		str[i] = sub[j++];
	}
	str[i] = '\0';
}
void mystrcat1(char* str,const char* sub) {
	while (*str != '\0') {
		str++;
	}
	while (*sub != '\0') {
		*str = *sub;
		str++;
		sub++;
	}
	*str = '\0';
}

9.4. strcmp(const char *s1, const char *s2)

比较两字符串,相等返回0;s1>s2返回1;s1<s2返回-1(按ASCII值比较)。

int mystrcmp(char* str, char* sub) {
	int i = 0;
	int a = 1;
	while (str[i] != '\0' && sub[i] != '\0') {
		if (str[i] != sub[i]) {
			a = 0;
			if (str[i] > sub[i]) {
				return 1;
			}
			else {
				return -1;
			}
		}
		i++;
	}
	if (a == 1) {
		return 0;
	}
}
int mystrcmp1(char* str, char* sub) {
	int i = 0;
	while (str[i] == sub[i]) {
		if (str[i] == '\0') {
			return 0;
		}
		i++;
	}
	return str[i] > sub[i] ? 1 : -1;
int mystrcmp2(const char* str, const char* sub) {
	while (*str != '\0' && *sub != '\0') {
		if (*str != *sub) {
			if (*str > *sub) {
				return 1;
			}
			else {
				return -1;
			}
		}
		str++;
		sub++;
	}
	if (*str != '\0') {
		return 1;
	}
	else if (*sub != '\0') {
		return -1;
	}
	else {
		return 0;
	}
}

10.mem系列函数    头文件#include<string.h>


10.1.memcpy  内存拷贝

不考虑内存重叠问题使用它前提条件 两个内存独立

10.2.memmove  内存拷贝

考虑内存重叠问题指针判断是否有重叠

11.面试题

1.大小端/大小字节序  --- 数据在内存中的存储模式 
小端 : 低地址存储低位数据("滴滴")      
int val = 0x12345678;       
_0x78__ _0x56__  __0x34__  _0x12__      
低地址                      高地址       
char* p = (char*)&val;   类型强转,只解析一个字节         
if( *p == 0x78) 小       
else     大   
大端: 与小端相反            
2. 数组指针 和 指针数组    
1) 数组指针  --> 指针   指针+1(偏移量,能力)
2) 指针 数组  --- 数组  每个元素是指针    
3) int arr[2];  int(*p)[2]=&arr;    数组指针   
const char* p[] = {"zs","lisi"};    指针数组
内容概要:本文围绕“基于改进秃鹰算法的微电网群经济优化调度”展开研究,提出了一种改进的秃鹰搜索算法(BES),旨在解决微电网群在复杂运行环境下的多目标、强约束、非线性及高维经济调度问题。通过引入特定优化策略,增强了基础算法的全局搜索能力和收敛效率,克服了传统智能算法易陷入局部最优的缺陷。研究构建了一个包含分布式电源、储能系统与多元负荷的微电网群调度模型,以最小化系统综合运行成本为核心目标,综合考虑功率平衡、设备出力能力、储能运行特性等多重约束条件。通过仿真实验验证了所提算法在调度精度、稳定性和计算效率方面相较于传统方法具有明显优势,并进一步展示了其在降低能源开支、提升可再生能源消纳水平方面的实际应用价值。; 适合人群:具备一定电力系统基础知识或优化算法背景,从事新能源调度、智能优化算法研究与应用等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于微电网群、综合能源系统等场景下的经济调度优化;②为秃鹰算法及其他群体智能算法的改进、复现与性能对比提供参考范例;③服务于科研仿真、算法验证及工程化应用需求。; 阅读建议:建议读者结合文中提供的Matlab代码实现进行实践操作,重点关注算法改进机制与调度模型的构建逻辑,同时可借助网盘资源获取完整资料,以加深对算法性能表现与应用场景的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值