当前位置: 首页 > 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。p,q 指向同一个变量了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) 80byte

2. 在执行 取地址操作

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(i=0;i<size;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'!=*(a+i) ) // { // printf("%c",*(a+i)); // 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(i=0;i<size;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 i=0;i<size;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 i=0;i<size;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 i=0;i<size;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.jsqmd.com/news/885019/

相关文章:

  • py每日spider案例之某乎请求头参数x-zse-96加密逻辑获取
  • 基于ESP32与LoRa的智能车库门远程监控系统DIY指南
  • 孝感黄金回收水深在哪?本地人真实踩坑经历分享,正规品牌全面测评 - 速递信息
  • 2026交流变频电机企业能力深度解析:全周期解决方案与交付保障 - 深度智识库
  • 终极开源吉他谱编辑器TuxGuitar深度解析:从插件架构到专业编曲实践
  • 3分钟解锁网易云音乐NCM格式限制:从加密困境到自由播放的完整解决方案探索
  • 镇江黄金回收靠谱怎么选?普通人踩坑真实经历复盘,本地品牌专业测评 - 速递信息
  • 键盘侦探:三分钟定位Windows热键冲突元凶
  • 上海裸钻钻戒横向对比 镶嵌款式影响实际成交价格 - 奢侈品回收测评
  • Unity 2020 AndroidX与Facebook SDK 12.x兼容实战指南
  • 2026 年 5 月大连二手奢包回收行业解读|添价收黄金奢侈品回收引领规范化发展 - 薛定谔的梨花猫
  • 第3章 谁在安全区——AI无法替代的五大核心能力
  • 如何用开源3D模型解决个性化机械键盘键帽定制难题?
  • 基于MAX78000与LoRa的无电池人脸识别相机:边缘AI与能量采集实战
  • 珍宝黄金回收:2026年5月桂林十年老店的黄金变现之道,专业与诚信并存 - 润富黄金珠宝行
  • DeepSeek推理加速实践全图谱(2024最新生产环境验证版)
  • Nginx解决跨域问题
  • 云南高价黄金回收怎么选?2026 正规机构推荐:铭亚黄金回收 - 资讯焦点
  • 告别手动重复操作:用AutoX.js 4.1.1在雷电模拟器上搭建自动化测试环境(附Total Control投屏配置)
  • 3步打造FPS游戏AI瞄准助手:基于YOLOv5的终极解决方案
  • Taotoken用量看板如何帮助个人开发者清晰掌握API消费
  • 机器学习加速粒子物理全局拟合:XGBoust在B介子反常分析中的应用
  • 特色小吃加盟县域创业者县城开店创业查找型全攻略爆脾气生炸鸡架县域小吃加盟推荐 - 资讯焦点
  • 零基础变身黑客精英!这几个宝藏网站带你从入门到精通,速收藏!
  • 2026年专利申报避坑指南|企业高价值专利合规布局与落地实操干货 - 速递信息
  • 从‘五彩纸屑’到‘史诗魔法’:如何用Unity ParticleSystem的Noise和Trails模块提升特效质感
  • 闲置黄金变现怕被坑?认准福昌夏等六家正规平台 - 黄金上门回收
  • SingleFile:如何解决网页内容离线保存的三大痛点?
  • 2026年安徽省SCMP培训选哪家?众智商学院课程特色与真实评价 - 众智商学院课程中心
  • 特色餐饮加盟景区创业者景区开店创业购买型景区餐饮加盟项目高客流高收益全解析 - 资讯焦点