C语言入门学习 --- 6.指针

文章目录

    • 第六章指针
      • 1.指针是什么?
        • 这里我们总结一下:
        • 问题:
        • 省流版:
      • 2.指针和指针类型
        • 2.1指针+-整数
        • 2.2指针的解引用
      • 3.野指针
        • 3.1野指针成因
        • 3.2如何规避野指针
      • 4.指针运算
        • 4.1指针+-整数
        • 4.2指针-指针
        • 4.3指针的关系运算
        • 标准规定:
      • 5.指针和数组
      • 6.二级指针
      • 7.指针数组
      • 练习:
      • 配套练习:

第六章指针

1.指针是什么

2.指针和指针类型

3.野指针

4.指针运算

5.指针和数组

6.二级指针

7.指针数组

1.指针是什么?

指针也就是内存地址,指针变量是用来存放内存地址的变量。

指针变量:可以通过使用&(取地址操作符)取出变量的内存地址,把地址存到一个变量中,这个变量就是指针变量。

#include <stdio.h>int main()
{int a = 5;   //在内存中开辟一块空间int* p = &a; //a的内存空间为4个字节,这里将第一个字节的地址存放在p变量中,则p就是一个指针变量。//使用&,取出a的地址放入p中return 0;
}
这里我们总结一下:

指针变量是用来存放地址变量的。(存放在指针中的值都被当成地址处理了)

问题:

一个小的单元是多大?

1个字节。

如何编排地址?

经过计算发现一个字节给一个对应的地址是较合适的。

对于32位的机器,在寻找地址的时候产生高电平(1)和低电平(0)。

那么32位的机器,产生的地址就会是:

00000000 00000000 00000000 0000000000000000 00000000 00000000 0000000100000000 00000000 00000000 0000001000000000 00000000 00000000 00000011........11111111 11111111 1111111 111111111

这里有2^32个地址。

到这里其实我们就可以明白:

  1. 在32位的机器中,地址是32个0或1组成二进制序列,地址就要用4个字节的空间来进行存储,所以一个指针变量大小就应该为4个字节。

  2. 那么如果在64位的机器上,那一个指针变量的大小就是8个字节。

省流版:
  1. 指针用来存放地址的,地址是唯一能够标识一块地址空间的。

  2. 指针的大小在32位平台为4个字节,在64位平台为8个字节。

2.指针和指针类型

    char* pa = NULL;int* pb = NULL;short* pc = NULL;long* pd = NULL;float* pe = NULL;double* pf = NULL;

可以看出,指针的定义方式是:type + *。

char*类型的指针是为了存放char类型变量的地址。

int*类型的指针是为了存放int类型变量的地址。

short*类型的指针是为了存放short类型变量的地址。

long*类型的指针是为了存放long类型变量的地址。

float*类型的指针是为了存放float类型变量的地址。

double*类型的指针是为了存放double类型变量的地址。

指针的类型有什么意义?(看以下内容)

2.1指针±整数
  int x = 5;int* pa = &x;char* pb = (char*)&x;printf("%p\n",pa);printf("%p\n", pa+1);printf("%p\n", pb);printf("%p\n", pb+1);    

省流:指针的类型决定了指针向前或者向后一步的距离有多大。

2.2指针的解引用
  int i = 0x12223242;char* pa = (char*)&i;   int* pb = &i;                         *pa = 0; //注意观察调试的过程中内存的变化*pb = 0; //注意观察调试的过程中内存的变化//调试->窗口->内存

总结:

指针的类型决定了对指针解引用的时候有多大的权限(就是能够操作几个字节)。

如:char *的类型解引用就只能访问一个字节,而int *类型解引用能访问四个字节。

3.野指针

野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

3.1野指针成因

1.指针未初始化

#include <stdio.h>int main()
{int *n;  //局部指针变量未初始化,默认是随机值*n = 8;return 0;
}

2.指针越界访问

#include <stdio.h>int main()
{int arr[10] = { 0 };int* pa = arr;for (int i = 0;i < 11;i++){//当指针指向的范围超过arr的范围时,p就是野指针*(pa++) = i;}return 0;
}

3.指针指向的空间释放

#include <stdio.h>int* test()
{int a = 2;return &a;
}int main()
{int* p = test();return 0;
}
3.2如何规避野指针

1.指针初始化

2.小心指针越界

3.指针指向空间释放即使置NULL

4.避免返回局部变量的地址

5.指针使用之前检查有效性

#include <stdio.h>int main()
{int* p = NULL;int a = 2;p = &a;if (p != NULL){*p = 4;}return 0;
}

4.指针运算

  • 指针±整数

  • 指针-指针

  • 指针的关系运算

4.1指针±整数
#include <stdio.h>#define x_num 5int main()
{float num[x_num];float* p;for (p = &num[0]; p < &num[x_num];){*p++ = 0;}return 0;
}
4.2指针-指针
int mystrlen(char* x)
{char* n = x;while (*n != '\0'){n++;}return n - x;
}
4.3指针的关系运算
for (p = &num[x_num]; p > &num[0];){*--p = 0;}

简化代码,修改如下:

for (p = &num[x_num]; p > &num[0]; p--){*p = 0;}

绝大部分的编译器上完成任务是没什么问题的,但还是避免这么些,因为标准并不能确保它可行。

标准规定:

允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。

5.指针和数组

#include <stdio.h>int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };printf("%p\n", arr);printf("%p\n", &arr[0]);return 0;
}

可知数组名和数组首元素的地址相同。

结论:数组名表示的是数组首元素的地址。(2种情况除外,之前的数组章节有详细讲解)

那么这样写代码是可以的:

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = arr;

既然数组名可以被当成地址存放到一个指针中,那么就可以直接通过指针来访问数组。

#include <stdio.h>int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };int i = 0;int* p = arr;int sz = sizeof(arr) / sizeof(arr[0]);for (i = 0; i < sz; i++){printf("%d ", *(p+i));}return 0;
}

6.二级指针

  int a = 2;int* pa = &a;int** ppa = &pa;

二级指针的运算:

*ppa通过对ppa中的地址进行解引用,*ppa其实访问的就是pa。

int b = 4;
*ppa = &b   //等价于 pa = &b;

**ppa先通过pa,进行解引用操作,访问的就是a。

**ppa = 30;
//等价于*pa = 30;
//等价于   

7.指针数组

指针数组是存放指针的数组

int *arr[5];

arr是一个数组,里面有五个元素,每个元素都是整型指针。

练习:

1.题目名称:计算求和

题目内容:求Sn=a+aa+aaa+aaaa+aaaaa的前五项之和,其中a是一个数字。

例如:2+22+222+2222+22222

#include <stdio.h>int main()
{int a = 0;int n = 0;scanf("%d %d", &a, &n);int sum = 0;int ret = 0;int i = 0;for (i = 0; i < n; i++){ret = ret * 10 + 2;sum += ret;}printf("sum的值为:%d", sum);return 0;
}

2.题目名称:打印数组内容

题目内容:写一个函数打印arr数组的内容,不使用数组下标,使用指针。arr是一个整形一维数组。

#include <stdio.h>void print(int* p, int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ",*(p+i));}printf("\n");
}int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };int sz = sizeof(arr) / sizeof(arr[0]);print(arr, sz);return 0;
}

3.题目名称:打印水仙花数

题目内容:求出0~100000之间的所有”水仙花数“并输出。

“水仙花数”是指一个n位数,其各位数字的n次方之和等于该数本身。

如:153=13+53+3^3,则153是一个水仙花数。

#include <stdio.h>
#include <math.h>int main()
{int i = 0;for (i = 0; i <= 100000; i++){int n = 1;int tmp = i;while (tmp / 10){n++;tmp = tmp / 10;}tmp = i;int sum = 0;while (tmp){sum += pow(tmp % 10, n);tmp = tmp / 10;}if (sum == i){printf("%d ", sum);}}return 0;
}

4.题目名称:字符串逆序

题目内容:写一个函数,可以逆序一个字符串的内容。

#include <stdio.h>void reverse(char* arr, int len)
{char* left = arr;char* right = arr + len - 1;while (left < right){char tmp = *left;*left = *right;*right = tmp;left++;right--;}
}int main()
{char arr[] = "abcdef";int len = strlen(arr);reverse(arr, len);printf("%s", arr);return 0;
}

5.题目名称:打印菱形

#include <stdio.h>int main()
{int i = 0;int line = 0;scanf("%d", &line);for (i = 0; i < line; i++){int j = 0;for (j = 0; j<line -1 - i; j++){printf(" ");}for (j = 0; j < 2 * i + 1; j++){printf("*");}printf("\n");}for (i = 0; i < line - 1; i++){int j = 0;for (j = 0; j <= i; j++){printf(" ");}for (j = 0; j < 2 * (line - 1 - i) - 1; j++){printf("*");}printf("\n");}return 0;
}

6.题目名称:喝汽水问题

题目内容:喝汽水,一瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以多少汽水。

#include <stdio.h>int main()
{int money = 20;int total = money;;int empty = money;while (empty >= 2){total += empty / 2;empty = empty / 2 + empty % 2;}printf("%d", total);return 0;
}

上一章:C语言入门学习 — 5.操作符

配套练习:

C语言练习题110例(一)
C语言练习题110例(二)
C语言练习题110例(三)
C语言练习题110例(四)
C语言练习题110例(五)
C语言练习题110例(六)
C语言练习题110例(七)
C语言练习题110例(八)
C语言练习题110例(九)
C语言练习题110例(十)
C语言练习题110例(十一)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/740616.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

剑指offer面试题34 丑数

考察点 空间换时间提效知识点 题目 分析 这里面其实用到了一点点的数学知识&#xff0c;丑数的定义是只包含2&#xff0c;3&#xff0c;5因子的数。现在要求第1500个丑数&#xff0c;最简单的办法就是从数字1开始遍历&#xff0c;依次判断每个数字是不是丑数&#xff0c;如果…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的木材表面缺陷检测系统(深度学习+Python代码+UI界面+训练数据集)

摘要&#xff1a;开发高效的木材表面缺陷检测系统对于提升木材加工行业的质量控制和生产效率至关重要。本篇博客详细介绍了如何运用深度学习技术构建一个木材表面缺陷检测系统&#xff0c;并提供了完整的实现代码。该系统采用了强大的YOLOv8算法&#xff0c;并对YOLOv7、YOLOv6…

升级Windows 11 专业版升级密钥永久使用

Windows 11 专业版是 Windows 11 的商业版本&#xff0c;专为中小型企业和组织设计。它提供了一些家庭版和专业版所没有的功能&#xff0c;例如&#xff1a; 安全性: 设备加密&#xff1a;使用 BitLocker 或 BitLocker 设备加密保护您的设备和数据。身份验证&#xff1a;使用…

VUE_nuxt启动只能通过localhost访问,ip访问不到:问题解决

修改项目根目录下的 package.json "config": {"nuxt": {"host": "0.0.0.0","port": "3000"} } 这样项目启动后就可以通过ip进行访问了

保研复习数据结构记(7)--散列查找(哈希表)

哈希表有什么特点&#xff1f;数据元素的关键字与其存储地址直接相关&#xff08;通过哈希函数相关&#xff09;&#xff0c;典型的用空间换时间的算法处理冲突的方法&#xff1f;拉链法&#xff08;链地址法&#xff09;&#xff0c;开放定址法&#xff0c;再散列法什么是查找…

mac idea快捷键记录

1.查看接口有多少的实现类&#xff0c;选中下面的这个类&#xff0c;然后commandoptionB 即可。

【JavaEE Spring 项目】消息队列的设计

消息队列的设计 一、消息队列的背景知识二、需求分析核心概念⼀个⽣产者, ⼀个消费者N 个⽣产者, N 个消费者Broker Server 中的相关概念核⼼ API交换机类型 (Exchange Type)持久化⽹络通信消息应答 三、 模块划分四、 项⽬创建五、创建核心类创建 Exchange创建 MSGQUeue创建 B…

【位运算】【脑筋急转弯】2749. 得到整数零需要执行的最少操作数

作者推荐 视频算法专题 本文涉及知识点 2749. 得到整数零需要执行的最少操作数 给你两个整数&#xff1a;num1 和 num2 。 在一步操作中&#xff0c;你需要从范围 [0, 60] 中选出一个整数 i &#xff0c;并从 num1 减去 2i num2 。 请你计算&#xff0c;要想使 num1 等于 …

对GIS与游戏引擎(UE4 或 U3D)结合的看法

GIS与游戏引擎结合&#xff0c;这在6年前就已经很多公司在进行探索了&#xff0c;经过这几年的发展&#xff0c;结合当前的政策&#xff0c;从以下几方面说一下我的看法&#xff1a; 1.GIS客户都是特殊单位及领域。2018年后&#xff0c;国内已经对国产化有明确要求了&#xff0…

Docker进阶:深入了解容器数据卷

Docker进阶&#xff1a;深入了解容器数据卷 一、前言二、容器数据卷的作用三、容器数据卷的使用方法四、实战--使用docker部署前端项目&#xff08;数据卷挂载&#xff09;4.1 重要&#xff1a;准备工作&#xff0c;先在本地创建挂载目录4.2 启动一个临时的nginx容器&#xff0…

LLM(大语言模型)常用评测指标之F1-Score

F1-Score F1-Score 是一种常用于评估分类模型性能的指标&#xff0c;特别是在数据不平衡的情况下。它是精确度 (Precision) 和召回率 (Recall) 的调和平均值&#xff0c;用于衡量模型对正类的预测能力。 计算方法 精确度 (Precision)&#xff1a;是指正确预测为正类的数量与所…

pytorch(九)卷积神经网络

文章目录 卷积神经网络全连接神经网络与卷积神经网络的区别概念性知识mnist数据集(卷积神经网络) GoogLeNetInception 残差网络ResNet残差块结构 稠密连接网络网络结构 卷积神经网络 全连接神经网络与卷积神经网络的区别 全连接神经网络是一种最为基础的前馈神经网络&#xf…

ChatGPT Prompt 的原理总结

ChatGPT Prompt 的原理总结 ChatGPT Prompt 是 OpenAI 开发的大型语言模型 ChatGPT 的一种使用方式。通过 Prompt&#xff0c;用户可以引导 ChatGPT 生成特定内容&#xff0c;例如回答问题、写故事、写代码等等。 Prompt 的原理 Prompt 本质上是一段文本&#xff0c;它告诉 C…

wrk安装及使用

一, mac安装 官网地址: https://github.com/wg/wrk/blob/master/README.md mac 安装: brew install wrk 查看是否安装成功: wrk -v centos安装: sudo yum groupinstall Development Tools sudo yum install -y openssl-devel git git clone GitHub - wg/wrk: Modern HTTP …

处理json异常问题,由于发送kafka消息是一个字符串,等到消费时json字符串会有多个““引号,故需要先处理json再转对象

发送一个正确的json对象 发送kafka消息也是一个json传&#xff0c;也没问题 等到消费kafka时&#xff0c;也能接收到一个json字符串但是会多一个 " 引号&#xff0c; 就会导致json转对象失败所以需要先去除 开通和结尾的 " 引号 去除后的json 就是一个正常的json&…

河北专升本(C语言编程题)

一&#xff1a;基础算法原理 1. 冒泡排序 原理&#xff1a;从左到右&#xff0c;相邻元素进行比较。每次比较一轮&#xff0c;就会找到序列中最大的一个或最小的一个。这个数就会从序列的最右边冒出来。 以从小到大排序为例&#xff0c;第一轮比较后&#xff0c;所有数中最大的…

Linux进程概念(2)

一、进程状态 Linux的进程状态实际上就是 struct task_struct 结构体中的一个变量 1.1状态汇总 其中&#xff0c;Linux 状态是用数组储存的&#xff0c;如下&#xff1a; static const char * const task_state_array[] { "R (running)", // 0 …

【Web世界探险家】打开Web世界的大门

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &…

唯众物联网+地理科学交付云南师范大学地理学部教学实验室项目

近日&#xff0c;云南师范大学地理学部教学实验室建设项目顺利交付。该项目的成功落地&#xff0c;标志着物联网技术与地理科学教育的深度融合&#xff0c;为云南师范大学的地理教学提供了全新的教学平台与资源。该项目以物联网技术为核心&#xff0c;结合地理科学的特点&#…

蓝桥杯算法错题记录-基础篇

文章目录 本文还在跟新&#xff0c;最新跟新时间3/11&#xff01;&#xff01;&#xff01; 格式一定要符合要求&#xff0c;&#xff08;输入&#xff0c;输出格式&#xff09;1. nextInt () next() nextLine() 的注意事项2 .数的幂 a^2等3.得到最大长度&#xff08;最大...&a…