当前位置: 首页 > news >正文

C语言(12) 指针的常见操作

指针的常见操作指针变量有两方面的意思:一个指针指向的内容(数据值一级)指针变量本身存储的数据 (地址值)#include stdio.h int main() { int a 10; int b 0 ; int c 50; int *p NULL; int *q NULL; p a; // 对指针变量本身进行修改 // 对指针指向的数据 进行操作 b *p ;// 通过地址获得地址中数据, 相当与是对 a变量的读取 *p 20;// 把需要写入的数据通过地址写入对应的内存 对a 变量的写入 p c; // p变量本身发生变化与c变量关联 b *p; // 对c变量读取操作 *p 10; //对 c变量的写入操作 q p;// 把p指向的地址赋值给q。pq 指向同一个变量了c。 return 0; }赋值运算符的左右值p做 左值 对指针变量本身进行修改 存储某个变量的地址p做 右值 把p指向的地址赋值给另外一个指针。p另一个 指向同一个变量了。*p做 左值 向指针指向的变量 写入数据*p做 右值 读出向指针指向的变量的数据指针作为参数 传参函数传递参数1. 值传递 在主调函数中实参在被调函数中形参。 形参可以读出实参的数据。但是不能修改实参的值。2.地址传递。 在主调函数中实参; 在被调函数中形参。 形参可以通过间接访问的方式读写实参的数据。实参和形参都是指针。这两个指针中存储的地址值同一个变量的地址。#include stdio.h int func(int a, int b, int* sum, int* sub) { *sum a b; *sub a - b; return 0; } int main(int argc, char** argv) { int a 10; int b 20; int sum 0; int sub 0; func(a, b, sum, sub); int *pa NULL; printf(a is %d b is %d sum:%d sub:%d\n, a, b, sum, sub); return 0; }函数使用指针作为参数1. 第一种情况需要形参修改实参的情况。需要被调函数修改主调函数中数据的值。2. 函数的返回值只有一个。 在被调函数中需要返回多个数据的话就需要传递值指针。因为在被调函数中可以修改主调函数的参数的只。void swap(int arg_a,int arg_b)//值传递 { int t arg_a; arg_a arg_b; arg_b t; } void swap2(int * pa,int *pb) //地址传递 { int t *pa; *pa *pb; *pb t; } int main() { int a 1; int b 2; //swap(a,b); swap2(a,b); printf(a is %d,b is %d\n,a,b); // 指针可以指向 任意0-4G地址 。但是不一定能读写内存有保护机制 int * p (int*)0x2000; }指针和数组的关系1. 数组名是一个指向数组第一元素的指针常量(指针本身的值不能发生变化。 指针是保存地址的变量指针保存的地址不能发生变化)。2. 数组名的类型 int a[] ; 类型 int [] int [ ] ≈ int * ;int [ ] ≈ int * ; c语言中兼容类型。大部分可以相互替换但是有例外。不同点1. sizeof()int* -- 8byte int a[20] - 20*sizeof(int) 80byte2. 在执行 取地址操作int*p - - int **(二级指针地址的地址)int a[10] - - int (*p)[10] (数组指针)int a[10] ; 对于数组名a 来说可以把他想成一个指针变量 。 本质 a 是数组中第一个元素地址的别名。一维数组做参数// int fill_array(int a[],int size) int fill_array(int *a, int size) { int i 0; // for(i0;isize;i) // { // a[i] rand()%50; // } for (i 0; i size; i) { //(*a)i rand()%50; *(a i) rand() % 50; } return 0; }一维字符数组做参数#include stdio.h //void show_str(char a[]) void show_str(char *a) { int i 0 ; // while(\0!a[i]) // { // printf(%c,a[i]); // i; // } // printf(\n); // while(\0!*(ai) ) // { // printf(%c,*(ai)); // i; // } // printf(\n); while(\0!*a) { printf(%c,*(a)); } printf(\n); } int main(int argc, char **argv) { char str[100]{0};// char [] -- char * printf(input str); gets(str); show_str(str); return 0; }字符指针常见错误#include stdio.h int main(int argc, char **argv) { //char *p hello; // hello 在内存中只用一份只能读取不能修改 char p[] hello; // char [] 开辟空间会把hello字符串常量复制一份给数组。 printf(%s\n, p); *(p 0) e; // 如果是指针操作是错误不能修改常量 p[0] e; // 如果是数组操作是对的修改的是数组里的内容不是字符串常量 printf(%s\n, p); return 0; }野指针#include stdio.h void swap(int *a,int *b) { int *t; // int t; *t *a; // t *a; // *t ,是野指针 *a *b; *b *t; } int main(int argc, char **argv) { int a 10; int b 20; swap(a,b); /* */ return 0; }函数指针指针函数1. 指针函数函数的返回值是 指针类型 。char *strcpy(char *dest, const char *src);strcpy 这个函数的返回值就是一个指针。 成功指针指向 dest。1 不能返回是局部作用域的指针。2 希望函数可以连续调用。 在同一个语句里面。 strcpy(str1,strcpy(str3,str2));3希望返回一端内存区域 (数组堆空间)。#include stdio.h #if 0 int * func1() // 错的 { int a[10]{1,2,3,4,5,6};// 0x2000 这个数组是个局部变量 printf(a addr %p\n,a[0]); return a;// a a[0] 不要返回局部变量 } int * func2() //对的 { static int a[10]{1,2,3,4,5,6};// 0x2000 printf(a addr %p\n,a[0]); return a;// a a[0] } int main(int argc, char **argv) { int *p NULL; p func2(); printf(main p addr %p\n,p); printf(p[0] %d\n,p[0]); return 0; } //............................. int * fun3(int *a,int size) { a[1]a[3]a[5]20; return a; } int main(int argc, char **argv) { int a[10]{0};// 0x2000 int * p fun3(a,10); printf( a[1]:%d a[3]:%d\n,a[1],a[3]); printf( p[1]:%d p[3]:%d\n,p[1],p[3]); return 0; }#include stdio.h #include string.h int mystrcpy(char *dst, char *src) { while (*src) { *dst *src; dst; src; } *dst\0; return 0; } char* mystrcpy2(char *dst, char *src) { char * tmp dst; while (*src) { *dst *src; dst; src; } *dst\0; return tmp; } char* mystrcat(char *dst,char * src) { char* tmp dst; while(*dst) { dst; } while(*src) { *dst*src; src; dst; } *dst \0; return tmp; } int main(int argc, char **argv) { char str1[100]hello; char str2[100]ok; char str3[100]{0}; // char *strcpy(char *dest, const char *src); //strcpy(str1,strcpy(str3,str2));// strcpy(str3,str2); str3 , strcpy(str1,str3); //printf(str1 is %s\n,str1); // mystrcpy2(str1,mystrcpy2(str3, str2)); // printf(str1 is %s\n,str1); mystrcat(str3,mystrcat(str1,str2)); printf(str3 is %s\n,str3); return 0; }2. 函数指针前面介绍的指针基本都是指数据。函数指针指向一个函数。本质指针变量函数名是地址值。里面储存的代码对数据进行加减乘除操作的。目的避免代码的重复。 方便后期代码的扩展。函数功能的解耦合。回调函数一个函数被当作参数 传递给另外一个函数。 被传递这个参数(函数指针回调函数)被动调用。主调函数只是传参(函数)语法 int add(int a, int b) // int (*) (int,int) { return a b; } int main(int argc, char **argv) { int (*p)(int, int) add; // p 函数指针。 add 不能写成add(), 不是对add函数的调用 int a 10; int b 20; int ret 0; ret add(a, b); printf(add() is %d\n, ret); ret p(a, b); // 通过函数指针 对函数的调用 printf(p() is %d\n, ret); return 0; }#include stdio.h #include stdlib.h #include time.h int fill_array(int *a, int size) { int i 0; // for(i0;isize;i) // { // a[i] rand()%50; // } for (i 0; i size; i) { //(*a)i rand()%50; *(a i) rand() % 50; } return 0; } int find_num3(int* a,int size) { for(size_t i0;isize;i) { if(0 a[i]%3) { printf(%d\n,a[i]); } } return 0; } int find_num5(int* a,int size) // int (*) (int*,int) { // int a; int ; int* p ;int* for(size_t i0;isize;i) { if(0 a[i]%5) { printf(%d\n,a[i]); } } return 0; } //............................................... int div3(int num) // div3 - int (*) (int) { return 0 num %3; } int div5(int num) // div3 - int (*) (int) { return 0 num %5; } void find_num(int* a,int size, int (*fun) (int) ) { for(size_t i0;isize;i) { if( fun(a[i])) // if( div5(a[i])) { printf(%d\n,a[i]); } } } int main(int argc, char **argv) { srand(time(NULL)); int a[10]{0}; fill_array(a,10); //find_num3(a,10); find_num(a,10,div5); // div5(); return 0; }typedef 关键字取别名 给数据类型取别名1. 普通数据类型 去别名typedef 老数据类型名 新数据类型名 typedef unsigned char u8; typedef unsigned short u16; typedef char s8; int main(int argc, char **argv) { u8 a; // unsigned char u16 b; // unsigned short s8 c; // char return 0; }2. 简化函数指针的写法typedef int* (*PFUN)(int ,int ,char* ); // int* func(int a,int b ,char* c) // int* (*)(int ,int ,char* ) // { // return NULL; // } // int func2(int a,int b, int* (*pfun)(int ,int ,char* )) // { // return 0; // } int* func(int a,int b ,char* c) // int* (*)(int ,int ,char* ) { return NULL; } int func2(int a,int b, PFUN pfun) { char str[]{0}; pfun(1,2,str); return 0; }3.和结构体有关晚些介绍
http://www.rkmt.cn/news/1381900.html

相关文章:

  • 想深耕网络安全行业,这些必备条件缺一不可
  • 3步快速上手Whisper-WebUI:轻松实现语音转字幕的完整指南
  • 从零到一:手把手教你用Playwright+Pytest+Allure搭建数据驱动的UI自动化测试(含Yaml配置详解)
  • 告别手动抢茅台!3分钟部署i茅台自动预约系统终极指南
  • 第2章 谁在危险中——被AI替代的五类程序员
  • AutoClicker实战指南:Windows鼠标点击自动化的高效解决方案
  • 深圳翻译公司推荐:2026年专业语言服务商权威盘点 - 资讯焦点
  • Lucyd 应用上线 AI 实时翻译通话:对讲机式母语交流,智能眼镜厂商竞逐可穿戴 AI 平台新赛道
  • 如何在Windows 10/11上完美运行Android应用?WSABuilds v2407.40000.4.0_v2完整指南
  • java的继承和多态
  • 别让依赖毁了你的实验:记一次Vision Mamba复现中causal_conv1d与mamba-ssm的版本“打架”事件
  • 别再乱建索引了!用Explain的key_len字段,一眼看穿你的MySQL联合索引到底生效了几个字段
  • DIY智能USB充电器:基于电流检测与双稳态继电器的零功耗节能方案
  • 2026上海二次加压泵工厂实测排行:合规与性能双维度对比 - 资讯焦点
  • (毕业必看)实测好用的AI论文写作工具,毕业党收藏备用
  • 科普帖|你的论文“含金量“谁说了算?聊聊查重背后的免费工具
  • 如何零基础搭建专属原神私服:KCN-GenshinServer的图形化革命
  • 如何突破网盘限速瓶颈?LinkSwift直链解析工具让企业文件传输效率提升300%
  • Burp抓包失败的五大隐形墙与HTTPS解密断裂点排查指南
  • qobuz-dl终极实战指南:专业无损音乐下载工具架构解析与高效应用
  • 【RT-DETR实战】070、模型分析工具:PyTorch Profiler性能分析
  • 腾讯元宝GEO排名优化:2026年AI搜索流量抢占的系统性方法论 - 博客湾
  • 终极指南:如何用wechat-need-web插件突破微信网页版访问限制
  • 在数据预处理与分析流水线中集成大模型API进行智能标注与摘要
  • 珍宝黄金回收(十年老店)|2026 年 5 月扬州江都黄金回收行情解读、避坑技巧与 FAQ 在扬州江都区,提到黄金回收,很多老居民第一反应就是珍宝。 - 润富黄金珠宝行
  • AAAI 2025 | VHM:面向遥感图像分析的通用可信视觉语言模型
  • Proteus仿真进阶:给你的AT89C52温控风扇加上OLED显示和手机蓝牙遥控
  • Selenium自动化测试第一步:手把手教你在Win10/Win11上搞定ChromeDriver环境
  • 网安学习第24天 PHP安全——PHP反序列化
  • 在Ubuntu 20.04上从零搞定WAVEWATCHⅢ 6.07.0:一个Linux小白的踩坑与通关实录