前言:写东西一样要保存,ctrl s常按着,写了一晚上,第二天全没了,快要哭了。要不是自己在指针这里浪费了很多时间,我可能就不会重新写了,希望大家能看懂学会,别再走弯路了。

1.内存四区 。

a) 代码区。代码。
b)全局区。 全局的常量字符串常量,“abc"变量 。
c)栈区。系统自动开辟,系统自动释放。并不是很大。
d)堆区。动态开辟的内存,手动开辟,手动释放。大。

如这个i,上面for循环用了下面还能用,因为上面用的时候自动开辟,用完就直接释放了。

#include <stdio.h>
int main() {for (int i = 0; i < 8; i++)printf("%d", i);
}

2.地址:

把内存以单个字节为单位,分开。对每一个字节编号,这个编号就是地址。
如同宾馆,地址就是房间号
a)编号是连续的。
b) 唯一的。
c) 取地址运算符: &单目运算符优先级() [ ] . 结合性右往左。

 int a;//定义一个整数a&a;//&是取地址符,&a返回的是a的地址

3. 首地址

一段内存空间中第一个存储单元的地址。
存储单元
如整数 a,他占四个字节,他的储存单元就是字节,首地址就是第一个字节的地址

如一维数组a[5],他由五个整数组成,储存单元就是整数,首地址就是第一个数a[0]的地址,虽然a[0]有四个字节,并且a[0]的地址就是a[0]的第一个字节的地址,但他的存储单元就是第一个数a[1]。

现在是二维数组 a[ 2 ][ 2] ,它是由两个一维数组组成,储存单元是一维数组,首地址就是第一个一维数组的地址,也就是第一个一维数组第一个元素的地址。

写了整整一晚上,Chrome突然自己关闭了,打开之后全都没了。(欲哭无泪)
指针的变量定义、指针变量的赋值、指针变量的引用还有一些基础的就不重新写了,相信这些很多人都明白(不明白的看这里C语言指针变量–图示易懂),下面主要写大家都比较懵逼的****数组与指针
。(重新写,真的很蛋疼)

指针变量的加减

指针之间只有加减,而且不是指针和指针的加减,而是指针加减一些字节数

数组与指针

敲黑板

想要理解数组与指针,这两个概念是必须要好好弄明白的。

首地址:一段内存空间中第- -个存储单元的地址。存储单元。
指针变量的加减,以指针所指向的类型空间为单位进行偏移。

一维数组与指针

1.定义一个一维数组

数组名是这个数组的《首地址》
int a[5];
a指向a[0], a[0] 是int类型 的元素,a的类型就是 int *
&a这个地址指向整个数组,&a的类型int(*)[5];

下面可以看到,a和&a[0]是一样的,印证了a指向a[0]
a+1比a多四个字节。

 int a[5] = {1,2,3,4,5};printf("a:%d \n", a);printf("a+1:%d \n", a+1);printf("a[0]:%d \n", a[0]);printf("&a[0]:%d \n", &a[0]);a:1898984
a+1:1898988
a[0]:1
&a[0]:1898984

2.访问数组元素

下标法

int a[5] = {1,2,3,4,5};
for(int i=0;i<5;i++){printf("%d”, a[i]);
}
12345

指针法

#include <stdio.h>
int main() {int a[5] = {1,2,3,4,5};int* p = a; //p指向a[0]for (int i = 0; i < 5; i++) {printf("%d ", *(p + i));    //12345printf("%d ", *p++);         //12345  printf("%d ", * (a + i));   //12345// printf("%d ", * a ++ );}
}
*p : a[0]         * (p + 1): a[1]       *(p + 2): a[2]  这里的p是没有变的
P++       的p是会变

*(p + i) 加括号是因为单目运算符比双目的高,*和++都是单目
单目运算符是指运算所需变量为一个的运算符,双目就是两个。
不能 *a++运算,这样不合法

二维数组与指针

int a[3][4] = { 1,2,3, 4,5,6,7,8, 9,10, 11,12};

数组名: a
a是数组名,也是这个二维数组的首地址
a指向二维数组的第一个存储单元a[0][ ]。

a[2][3][4] 由 2个维数组 3个一维数组 4个int的元素组成,他的存储单元就是二维数组,a指向a[0][0]

注意,不管是多少维的,储存他的地址都是这样按条排列的,而不会是那种方形的。

概念区分

a,a[0],a[0][0]的地址

a指向a[0],a[0]指向a[0][0],a[0][0]的地址是其第一个字节的地址

int a[3][4] = { 1,2,3, 4,5,6,7,8, 9,10, 11,12};printf("&a %d\n", &a);printf("&a[0] %d\n", &a[0]);printf("&a[0][0] %d\n", &a[0][0]);20183524
20183524
20183524

可以看下上下两个代码,a是二维数组a[3][4]的数组名也是其首地址,a[0]是一维数组的数组名也是其首地址,所以a和&a是一样的 a[0]和&a[0]是一样的,但是a[0][0]是一个数值,是具体的数,&a[0][0]才是a[0][0]的地址

a和a+1

a指向a[0]这个一维数组。a的类型是: int(*)[4]; a+1 a的第0行 a+1第一行,a+2第二行 所以上面a+1比a的地址多16个字节(4*4)
a[0]指向a[0][0] , a[0]的类型是 int∗int *int∗ , a[0]+1比a[0]多四个字节

 int a[3][4] = { 1,2,3, 4,5,6,7,8, 9,10, 11,12};printf("a: %d\n", a);printf("a+1: %d\n", a + 1);********************************printf("a[0] %d\n", a[0]);printf("a[0]+1 %d\n", a[0] + 1);a:     20183524
a+1: 20183540a[0]   20183524
a[0]+1 20183528

&a和&a+1

&a+1比&a多了48个字节(12∗4)(12*4)(12∗4),这是因为 &a是指整个二维数组a 类型是int∗[3][4]类型是int * [3][4]类型是int∗[3][4]
&a[0]+1比 &a[0]多16个字节(4∗4)(4*4)(4∗4),这是因为 &a[0]指向整个一维数组a[0], 类型是int∗[4]类型是int *[4]类型是int∗[4]

 int a[3][4] = { 1,2,3, 4,5,6,7,8, 9,10, 11,12};printf("&a: %d\n", &a);printf("&a+1: %d\n\n", &a+1);*********************************printf("&a[0] %d\n", &a[0]);printf("&a[0]+1 %d\n", &a[0]+1);&a:     20379712
&a+1:   20379760&a[0]   20379712
&a[0]+1 20379728

∗a和∗a+1和∗(a+1)*a 和*a+1和*(a+1)∗a和∗a+1和∗(a+1)

  • a,*a和&a都是一样的,是这个二维数组的地址。
  • **a是取出 *a这个地址存放的数据,也就是a[0][0],也就是1。
  • *a+1:是a的地址加四个字节,相当于a[0][1]。
  • (a+1):先看a+1,a的类型是 int * [4],上面也说了,a+1比a多16个字节(4 * 4),所以地址多16,也就成了下一个一维数组的首地址a[1]的地址,改地址存的数是a[1]的第一个数a[1][0]是5,(a+1)取地址存的数,是5
int a[3][4] = {1,8,7,9,5,6,7,8,9,10,11,12};printf("*a: %d\n", *a);printf("**a: %d\n", **a);printf("*a+1: %d\n", *a+1);printf(" *(*a+1): %d\n", *(*a+1));printf("*(a+1): %d\n", *(a+1));printf(" *(*(a+1)): %d\n", *(*(a+1)));*a:            19921108
**a:        1
*a+1:      19921112
*(*a+1):   8
*(a+1):        19921124
*(*(a+1)):  5

查找m行n列的元素

下标:a[m][n]
行地址:*(a[m]+n)
数组名: *( *(a+m)+n)

int a[3][4];
a   int(*) [4]
&a  int(*)[3][4]
a[0]    int*
a[0][0] int

查找a的第二行第三列的元素

int a[3][4] = {1,8,7,9,5,6,7,8,9,10,11,12};printf("(2,3) %d\n\n", *(a[1]+2));printf("(2,3): %d\n\n", *(*(a+1)+2));(2,3): 7(2,3): 7

多维指针

多维指针和二维指针是一样的,还是先明白这两条
首地址:一段内存空间中第一个(也就是最大的那个)存储单元的地址。存储单元。
指针变量的加减,以指针所指向的类型空间为单位进行偏移。

如五维指针a[2][3][4][5][6]
从高往低去拆
其存储单元为四维指针

&a ——> 就是一个指向八位数组的指针
a——>指向一个四维数组,地址为∗类型为int(∗)[.][.][.][.]a ——>指向一个四维数组,地址为* 类型为 int(*)[. ][. ][.][. ]a——>指向一个四维数组,地址为∗类型为int(∗)[.][.][.][.]
a[0]——>指向三维数组,a[.][.][.],类型为int(∗)[.][.][.]a[0]——> 指向三维数组, a[.][.][.] ,类型为 int(*)[. ][. ][ .]a[0]——>指向三维数组,a[.][.][.],类型为int(∗)[.][.][.]
a[0][0]——>指向二维数组a[.][.],类型为int(∗)[.][.]a[0][0] ——>指向二维数组a[.][ .],类型为int(*)[ .][ .]a[0][0]——>指向二维数组a[.][.],类型为int(∗)[.][.]
a[0][0][0]——>指向一维数组a[.],类型int(∗)[.]a[0][0][0]——>指向一维数组a[.],类型int(*) [.]a[0][0][0]——>指向一维数组a[.],类型int(∗)[.]
a[0][0]0][0]——>指向一个数,地址,类型为int∗a[0][0]0][0] ——>指向一个数,地址,类型为int*a[0][0]0][0]——>指向一个数,地址,类型为int∗
a[0][0]0][0][0]——>就是一个数,类型为inta[0][0]0][0][0] ——>就是一个数,类型为inta[0][0]0][0][0]——>就是一个数,类型为int

例题1:输出五个数

#include <stdio.h>
int main()
{ int a[5]={1,3,8,4,0};int i;for(i=0;i<5;i++){printf("%d ",*(a+i)); printf("%d ",&(a[i])); printf("%d ",(a+i));printf("\n");}return 0;}
1 1703708 1703708
3 1703712 1703712
8 1703716 1703716
4 1703720 1703720
0 1703724 1703724

先看上图,(a+i)指向a[i]的地址(相当于&a[i]),所以*(a+i)为改地址对应的数。经观察可以发现,a[i+1]比a[i]的地址多4,这是因为int (包括float, long)占4个字节(char 1个字节)。

例题2

int main()
{int a[5] = { 1, 2, 3, 4, 5};int* p, i;for (p = a; p < (a + 5); p++) {printf("%d ", *p);   printf("%d ", p);       printf("\n");}return 0;
}1 13826004
2 13826008
3 13826012
4 13826016
5 13826020

与例题1相同,这个只是设了一个指针变量*p,然后先将a[0]赋值给p,通过让后p++(实际上是每次p+1时,将a[0]的地址数加了4)改变a[0]的地址,通过新地址来找对应的a[i]。
优点: 用指针变量直接指向元素,不必每次都重新计算地址,像p++这样的自加操作是比较快的
这种有规律地改变地址值(p++)能大大提高执行效率

例题3

#include <stdio.h>
int main()
{ int i,a[5],*p=a;//printf("please enter 5 integer numbers:");for(i=0;i<5;i++)scanf("%d",p++);p=a;   for(i=0;i<5;i++,p++){printf("%d ",*p);printf("%d ",p);printf("%d ",a[i]);printf("\n");}return 0;
}
please enter 5 integer numbers:1 3 5 2 6
1 1703704 1
3 1703708 3
5 1703712 5
2 1703716 2
6 1703720 6

ok 今天先写这些,剩下的尽量明天写吧,当然还指针有很多很多:

  • 指针数组: int*[ ]
  • 数组指针: int(*)[ ]
  • 函数指针:
  • 指针形参的函数:
  • 结构体指针:
  • 字符串与指针:
  • 指向指针的指针:

参考与B站真的很清晰透彻 C语言Plus

这里是字符与指针,让你对指针更熟悉

这里是有关指针的编程题,期末不挂科系列

毕竟是小白,从小白视角看可能不会太深,但像我一样的小白应该都能看懂。
这篇博客主要是写给新手的,希望大家都能学懂学好,嘿嘿,写的不好还望大佬勿喷。

小白来学C语言之数组与指针相关推荐

  1. 小白来学C语言之字符串与指针

    初学C语言,指针的确是一个坎,但这又是基础,不得不学.真的学了好久,总是一知半解,也不怎么会做题,写下这篇博客,希望能帮助刚出门的小白,后续还有C语言指针例题以及详解. 不怎么会C语言数组与指针的可以 ...

  2. c语言如何用指针操作一维字符数组,C语言中数组和指针的互操作

    C是一种怀旧的语言,因为它的历史很久远,然而自从各种面向对象的编程语言的相续出现让它的影响力日减.当然了,这是无可非议的,但是C的高效性是其他语言无妨比拟的,所以我们有必要把握其中的精华与奥妙,也就有 ...

  3. 小白来学C语言之结构体

    文章目录 概念 为什么要有结构体? 定义和使用结构体变量 自己建立结构体类型 定义结构体类型变量 结构体变量的初始化和引用 使用结构体数组 定义结构体数组 结构体指针 指向结构体变量的指针 指向结构体 ...

  4. 一道题目让你看出C语言的数组与指针的区别:

    文章目录 题目概述: 输入格式: 输出格式: 输入输出样例: C语言题解: 错误的运行结果: 错误问题的分析与定位: C库的malloc函数讲解: 函数原型: 函数形参: 函数的返回值: 内存的释放: ...

  5. C语言字符数组、指针总结

    一. 字符串与字符数组 c语言没有字符串类型,用字符数组存放字符串. 字符指针有以下几种: 第一种: char a='c'; char* p=&a;//将a的地址赋给字符指针p *p='d'; ...

  6. C语言:数组与指针详解

    文章概述 本文章讲述关于C语言的主要内容如下:   1.字符数组.2.一维数组与指针.3.二维数组与指针.4.字符串与指针.5.字符串指针数组 一.字符数组   定义一维数组时,系统会在内存中为其分配 ...

  7. c语言三维数组 三维指针,C语言 通过指针访问一维数组,二维数组,三维数组。...

    /** 通过指针来访问一维数组,二维数组,多维数组 */ #include const int COLS=3; const int COUNT=4; //通过一级指针,计算偏移量来遍历一维数组 voi ...

  8. 小白来学C语言之宏定义(#define)

    毕竟是小白,从小白视角看可能不会太深,但应该都能看懂. 这篇博客就是也是写给新手的,希望大家都能学懂学好,嘿嘿,写的不好还望大佬勿喷. 可以使用#define 伪指令来定义一个宏. 宏分为不带参数的宏 ...

  9. 【一起来学C语言】数组(二)

    [前言] 上篇博客介绍了一维数组和二维数组,其实关于数组,还有一个很重要的角色--字符数组.在C语言中没有专门的字符串变量,那么该如何存放字符串呢?答案就是借用数组.本篇简介字符数组相关内容. [字符 ...

最新文章

  1. 中国7位学者当选!又一院士名单公布
  2. lighttpd+PHP上传文件
  3. 大话数据结构 :排序
  4. 百度推出新技术 MIP,网页加载更快,广告呢?
  5. Spark Structure Streaming(一)之简介
  6. LeetCode 868. 二进制间距(位运算)
  7. 【Nacos】Nacos MySQL 配置后无法登录 愚蠢的问题
  8. 算法-01-二分查找/插值查找
  9. 使用WIN32汇编语言实现一个基本windows窗口的过程分析
  10. 设计模式-05.建造者模式与模板方法模式比较
  11. Java MD5加密工具类
  12. 树莓派29/100 - 树莓派接上Kindle的墨水屏是什么体验?
  13. 台式计算机睡眠快捷键,电脑如何设置快捷方式迅速进入睡眠的状态?
  14. Altium Designer——usb信号线布线注意的问题——应使用差分布线
  15. php观察者模式,组合ArmyVisitor抽象类,用accept()方法将访问者对象传递给当前对象的所有的子元素,当前组件是一个组合体
  16. python傅里叶变换 信号处理 序列_(十六)数字图像处理中的傅里叶(DFT/FFT)
  17. 十进制和二进制换算。vb版本
  18. windows10计算机放桌面,将win10计算器放在桌面上的操作方法
  19. 仿淘宝商品界面(html div+css)
  20. 大数据风控是在做什么?

热门文章

  1. vue使用高德地图画电子围栏_Vue.js 中使用高德地图定位及渲染地图
  2. win10清理_无需第三方,win10也可以实现自动清理垃圾
  3. mysql索引别名_Mysql索引知识详谈
  4. NBU对oracle数据库进行rman备份
  5. access2007连接oracle数据库(通过ODBC)
  6. iphone微信美颜插件_iOS13.5 插件分享
  7. oracle查询表字段横向排序,sql 查询 - 横着走的螃蟹 - OSCHINA - 中文开源技术交流社区...
  8. Caused by: org.apache.catalina.LifecycleException: A child container failed during start
  9. Appium - 一个投巧的办法去验证页面是否存在某个元素
  10. html地址--待更新