前言:写东西一样要保存,ctrl s常按着,写了一晚上,第二天全没了,快要哭了。要不是自己在指针这里浪费了很多时间,我可能就不会重新写了,希望大家能看懂学会,别再走弯路了。
a) 代码区。代码。
b)全局区。 全局的常量字符串常量,“abc"变量 。
c)栈区。系统自动开辟,系统自动释放。并不是很大。
d)堆区。动态开辟的内存,手动开辟,手动释放。大。
如这个i,上面for循环用了下面还能用,因为上面用的时候自动开辟,用完就直接释放了。
#include
int main() {
for (int i = 0; i < 8; i++)
printf("%d", i);
}
把内存以单个字节为单位,分开。对每一个字节编号,这个编号就是地址。
如同宾馆,地址就是房间号
a)编号是连续的。
b) 唯一的。
c) 取地址运算符: &单目运算符优先级() [ ] . 结合性右往左。
int a;//定义一个整数a
&a;//&是取地址符,&a返回的是a的地址
一段内存空间中第一个存储单元的地址。
存储单元
如整数 a,他占四个字节,他的储存单元就是字节,首地址就是第一个字节的地址
如一维数组a[5],他由五个整数组成,储存单元就是整数,首地址就是第一个数a[0]的地址,虽然a[0]有四个字节,并且a[0]的地址就是a[0]的第一个字节的地址,但他的存储单元就是第一个数a[1]。
现在是二维数组 a[ 2 ][ 2] ,它是由两个一维数组组成,储存单元是一维数组,首地址就是第一个一维数组的地址,也就是第一个一维数组第一个元素的地址。
写了整整一晚上,Chrome突然自己关闭了,打开之后全都没了。(欲哭无泪)
指针的变量定义、指针变量的赋值、指针变量的引用还有一些基础的就不重新写了,相信这些很多人都明白(不明白的看这里C语言指针变量–图示易懂),下面主要写大家都比较懵逼的****数组与指针。(重新写,真的很蛋疼)
指针之间只有加减,而且不是指针和指针的加减,而是指针加减一些字节数
想要理解数组与指针,这两个概念是必须要好好弄明白的。
首地址:一段内存空间中第- -个存储单元的地址。存储单元。
指针变量的加减,以指针所指向的类型空间为单位进行偏移。
数组名是这个数组的《首地址》
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
int a[5] = {1,2,3,4,5};
for(int i=0;i<5;i++){
printf("%d”, a[i]);
}
12345
#include
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)); //12345
printf("%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]指向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[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]的类型是 i n t ∗ 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: 20183540
a[0] 20183524
a[0]+1 20183528
&a+1比&a多了48个字节 ( 12 ∗ 4 ) (12*4) (12∗4),这是因为 &a是指整个二维数组a 类 型 是 i n t ∗ [ 3 ] [ 4 ] 类型是int * [3][4] 类型是int∗[3][4]
&a[0]+1比 &a[0]多16个字节 ( 4 ∗ 4 ) (4*4) (4∗4),这是因为 &a[0]指向整个一维数组a[0], 类 型 是 i n t ∗ [ 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
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
下标: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 — — > 指 向 一 个 四 维 数 组 , 地 址 为 ∗ 类 型 为 i n t ( ∗ ) [ . ] [ . ] [ . ] [ . ] a ——>指向一个四维数组,地址为* 类型为 int(*)[. ][. ][.][. ] a——>指向一个四维数组,地址为∗类型为int(∗)[.][.][.][.]
a [ 0 ] — — > 指 向 三 维 数 组 , a [ . ] [ . ] [ . ] , 类 型 为 i n t ( ∗ ) [ . ] [ . ] [ . ] a[0]——> 指向三维数组, a[.][.][.] ,类型为 int(*)[. ][. ][ .] a[0]——>指向三维数组,a[.][.][.],类型为int(∗)[.][.][.]
a [ 0 ] [ 0 ] — — > 指 向 二 维 数 组 a [ . ] [ . ] , 类 型 为 i n t ( ∗ ) [ . ] [ . ] a[0][0] ——>指向二维数组a[.][ .],类型为int(*)[ .][ .] a[0][0]——>指向二维数组a[.][.],类型为int(∗)[.][.]
a [ 0 ] [ 0 ] [ 0 ] — — > 指 向 一 维 数 组 a [ . ] , 类 型 i n t ( ∗ ) [ . ] a[0][0][0]——>指向一维数组a[.],类型int(*) [.] a[0][0][0]——>指向一维数组a[.],类型int(∗)[.]
a [ 0 ] [ 0 ] 0 ] [ 0 ] — — > 指 向 一 个 数 , 地 址 , 类 型 为 i n t ∗ a[0][0]0][0] ——>指向一个数,地址,类型为int* a[0][0]0][0]——>指向一个数,地址,类型为int∗
a [ 0 ] [ 0 ] 0 ] [ 0 ] [ 0 ] — — > 就 是 一 个 数 , 类 型 为 i n t a[0][0]0][0][0] ——>就是一个数,类型为int a[0][0]0][0][0]——>就是一个数,类型为int
ok 今天先写这些,剩下的尽量明天写吧,当然还指针有很多很多:
参考与B站真的很清晰透彻 C语言Plus
这里是字符与指针,让你对指针更熟悉
这里是有关指针的编程题,期末不挂科系列