c语言中数组解引用是什么,C语言中数组的总结

#目录 #

一维数组的创建和初始化

一维数组的使用

一维数组在内存中的存储

指针的初步介绍

一维数组的指针访问

二维数组的创建和初始化

二维数组的使用

二维数组在内存中的存储

二维数组的指针访问

有关数组的运算

数组作为函数参数

1.一维数组的创建和初始化

数组的创建:在创建数组时,我们必须定义数组的类型和大小,数组的大小不能为0,数组中的元素类型都是相同的。

eg:

int arr[10];//[]内必须是常量/常量表达式(3+8),不能是一个变量(x...)

数组的初始化:在数组创建时,我们也要必须为数组初始化。

eg:

int arr1[3] = {1, 2, 3};

int arr2[] = {1, 2, 3};//在这里,我们arr[3]里边的数字可以不用写;

int arr3[3] = {1, 2};//也是可以的,只是把最后一个数初始化为0了而已

int arr4[3] = {1, 2, 3, 4};//是不可以的,不能超过数组长度

char arr5[3] = {'a', 98, 'c'};//因为是字符类型,所以98其实就是字符'b'

char arr6[] = "abcdef";

#include

int main()

{

char arr1[] = { 'a', 'b', 'c' };

char arr2[4] = "abc";

char *p = "abc";//这里只是把a的地址放进了p里边

return 0;

}

在内存中的存储:

210630117_1_20201221080330583

2.一维数组的使用

eg:

#include

int main()

{

int arr[10] = { 0 };

int i = 0;

for (i = 0; i < 10; i++)//i<11是不可以的,不可以越界访问

{

arr[i] = i;

}

return 0;

}

数组是使用下标来访问的,下标是从0开始。

数组的大小可以通过计算得到。(sz = sizeof(arr)/sizeof(arr[0]));

3.一维数组在内存中的存储

eg:

#include

int main()

{

int arr[10] = { 0 };

int i = 0;

for (i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)

{

printf("&arr[%d] = %p\n", i, &arr[i]);

}

return 0;

}

210630117_2_20201221080330879

从输出结果我们可以看出数组元素在内存中的存储是:地址是由低到高并且是连续存储的。

4. 指针的初步介绍

指针可以理解为一个变量,是一个专门用来存放地址的一个变量。

eg:

int *ptr = NULL;//定义一个整型的指针变量,初始化为NULL

char *ptr = NULL;//定义一个字符的指针变量,初始化为NULL

5. 一维数组的指针访问

eg:

#include

int main()

{

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

printf("%p\n", arr);

printf("%d\n", *arr);

return 0;

}

210630117_3_2020122108033120

从输出结果我们可以看出数组名其实存放的就是首元素的地址

eg:

int main()

{

int arr[10] = { 0 };

int i = 0;

int sz = sizeof(arr) / sizeof(arr[0]);

int *p = arr;

for (i = 0; i < sz; i++)

{

//arr[i] = i; (1)

*(p + i) = i; (2)

}

for (i = 0; i < sz; i++)

{

printf("%d\n", arr[i]);//(1)和(2)的输出结果一样

}

return 0;

}

210630117_4_2020122108033167

从输出结果我们可以看出,我们定义了一个指针p,指向arr,然后我们通过指针来访问数组。

6. 二维数组的创建和初始化

eg:

#include

int main()

{

int arr[3][4] = { 1, 2, 3, 4, 5, 6 };

//int arr[][4] = {{1, 2},{3, 4, 5},{6}};可以

//arr[3][] = {{1, 2},{3, 4, 5},{6}};是不可以的

return 0;

}

210630117_5_20201221080331161

从监视窗口我们可以看到,一行有四个元素,总共有三行,当后边元素没有初始化的时候,全默认为0。

7. 二维数组的使用

二维数组的使用也是通过下标方式

eg:

#include

int main()

{

int arr[3][5] = { 0 };

int i = 0;

int j = 0;

for (i = 0; i < 3; i++)

{

for (j = 0; j < 5; j++)

{

arr[i][j] = i * 5 + j + 1;

}

}

for (i = 0; i < 3; i++)

{

for (j = 0; j < 5; j++)

{

printf("%d ", arr[i][j]);

}

printf("\n");

}

return 0;

}

210630117_6_20201221080331317

8. 二维数组在内存中的存储

我们可以通过打印它的地址来观察它是如何存储的。

eg:

#include

int main()

{

int arr[3][5] = { 0 };

int i = 0;

int j = 0;

for (i = 0; i < 3; i++)

{

for (j = 0; j < 5; j++)

{

printf("&arr[%d][%d] = %p\n", i, j, &arr[i]);

}

}

return 0;

}

210630117_7_20201221080331583

我们可以看出数组元素的地址是连续的,并没有进行换行,我们只是把它假想成了三行。

9. 二维数组的指针访问

我们知道了一维数组的内存存储模式之后,我们尝试使用指针对一维数组进行访问,那在这里,我们尝试使用指针来访问我们的二维数组。

eg:

#include

int main()

{

int arr[3][5] = { 0 };

int *p = &arr[0][0];

int i = 0;

int j = 0;

for (i = 0; i < 15; i++)

{

*(p + i) = i + 1;

}

for (i = 0; i < 3; i++)

{

for (j = 0; j < 5; j++)

{

printf("%d ", arr[i][j]);

}

}

return 0;

}

指针也存在类型:

eg:

#include

int main()

{

int num = 0x11223344;

int *p = &num;

*p = 0;

return 0;

}

210630117_8_20201221080331739

这里的指针p是int型,所以我们对它的改变,是改变4个字节的大小,同样的,如果我们对p进行加1操作,指针向后跳4个字节。

eg:

#include

int main()

{

int num = 0x11223344;

//int *p = &num;

//*p = 0;

char *pc = &num;

*pc = 0;

return 0;

}

210630117_9_20201221080331942

我们可以从内存中观察到,只改变了1个字节的大小,因为pc指针的类型是char。如果我们对pc进行加1操作,指针向后跳1个字节。

eg:

#include

int main()

{

int arr[10] = { 0 };

printf("%p\n", &arr[0]);

printf("%p\n", &arr[0] + 1);

printf("---------------\n");

printf("%p\n", arr);

printf("%p\n", arr + 1);

printf("---------------\n");

printf("%p\n", &arr);

printf("%p\n", &arr + 1);

return 0;

}

210630117_10_2020122108033283

我们可以从输出结果看出&arr[0],arr,&arr它们的地址虽然相同,但它们的意义是不同的,&arr,取的是数组的地址,对它进行加1,就相当于跳过整个数组,又因为数组是int型,总共有10个元素,所以跳过的字节大小是40。

10. 有关数组的运算##

关于数组我们必须要学会有关数组的一些运算。

eg:

#include

int main()

{

//一维数组

int a[] = { 1, 2, 3, 4 };

printf("%d\n", sizeof(a));//16

//1.数组名单独放在sizeof内部,数组名表示整个数组,所以sizeof(数组名)计算的是是数组总大小,单位是字节

//2.&数组名,数组名表示整个数组,所以&数组名取出的是整个数组的地址

//3.除此之外,所有的数组名都表示首元素的地址

printf("%d\n", sizeof(a + 0));//4 a代表首元素地址,a+i代表第i个元素的地址,在32位平台下所有的地址的大小都是4个字节

printf("%d\n", sizeof(*a));//4 a是首元素地址,*a是首元素--1,int型占4个字节大小

printf("%d\n", sizeof(a + 1));//4 a是首元素地址,a+1是第二个元素的地址,它还是一个地址

printf("%d\n", sizeof(a[1]));//4 a[1]--第二个元素

printf("%d\n", sizeof(&a));//4 &a虽然取出的是整个数组的地址,但它还是一个地址

printf("%d\n", sizeof(*&a));//16 &a取出的是整个数组的地址,对它进行解引用,就是这个数组,这个数字的大小就是16

printf("%d\n", sizeof(&a + 1));//4 &a取出的是整个数组的地址,加1跳过了整个数组(16个字节),但它还是一个地址

printf("%d\n", sizeof(&a[0]));//4 &a[0]取的是第一个元素的地址

printf("%d\n", sizeof(&a[0] + 1));//4 &a[0] + 1取的是第二个元素的地址

return 0;

}

210630117_11_20201221080332208

#include

int main()

{

//字符数组

char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };

printf("%d\n", sizeof(arr));//6

printf("%d\n", sizeof(arr + 0));//4 首元素地址

printf("%d\n", sizeof(*arr));//1 首元素地址解引用是首元素(a),char类型占1个字节

printf("%d\n", sizeof(arr[1]));//1 首元素

printf("%d\n", sizeof(&arr));//4 数组的地址

printf("%d\n", sizeof(&arr + 1));//4 下一个数组的地址,跳过了f

printf("%d\n", sizeof(&arr[0] + 1));//4 第二个元素的地址

printf("%d\n", strlen(arr));//随机值 strlen()求的是字符串长度,以'\0'为结束标志,这里并没有'\0',所以会一直往后数

printf("%d\n", strlen(arr + 0));//随机值 还是从'a'开始数,但没有'\0',所以停不下来

printf("%d\n", strlen(*arr));//程序会崩掉 strlen()接收的是一个地址,*arr是字符'a',这里把'a'的ASCII码值(97)作为一个地址访问,这一块的地址是不能被访问的

printf("%d\n", strlen(arr[1]));//错误 传的是'b',和传的是'a'效果一样

printf("%d\n", strlen(&arr));//随机值 &arr虽然取的是数组的地址,但数组的地址和数组首元素的地址是一样的,也是从‘a'开始数,但并没有'\0'

printf("%d\n", strlen(&arr + 1));//随机值 但这个随机值和前边的随机值意义不同,它是把'a','b','c','d','e','f'跳过去了,从f后边开始数

printf("%d\n", strlen(&arr[0] +1));//随机值 这个是从'b'开始往后数的

return 0;

}

210630117_12_20201221080332317

#include

int main()

{

char arr[] = "abcdef";

printf("%d\n", sizeof(arr));//7 里边还有'\0',只不过我们看不到而已

printf("%d\n", sizeof(arr + 0));//4 arr+0---首元素地址

printf("%d\n", sizeof(*arr));//1 对首元素地址解引用是首元素

printf("%d\n", sizeof(arr[1]));//1 第二个元素

printf("%d\n", sizeof(&arr));//4 数组的地址也是地址

printf("%d\n", sizeof(&arr + 1));//4 也是一个地址,不过这个地址在'\0'后边,跳过了整个数组

printf("%d\n", sizeof(&arr[0] + 1));//4 从b开始的一个地址

printf("%d\n", strlen(arr));//6 strlen()以'\0'为结束标志,但不算'\0'

printf("%d\n", strlen(arr + 0));//6 arr+0与arr都代表首元素地址

printf("%d\n", strlen(*arr));//错误 这传进来的不是一个地址,而是一个字符

printf("%d\n", strlen(arr[1]));//错误

printf("%d\n", strlen(&arr));//6 数组的地址也是首元素地址,地址的位置是一样的

printf("%d\n", strlen(&arr + 1));//随机值 跳过了'\0',从'\0'往后数,不知道会数到哪里去

printf("%d\n", strlen(&arr[0] + 1));//5 从第二个元素(b)开始往后数,遇到'\0'结束

return 0;

}

210630117_13_20201221080332426

#include

int main()

{

char *p = "abcdef";

printf("%d\n", sizeof(p));//4 p是指针变量,里边存的是a的地址

printf("%d\n", sizeof(p + 1));//4 还是一个地址,不过是指向了b的地址

printf("%d\n", sizeof(*p));//1 对a的地址解引用就是a

printf("%d\n", sizeof(p[0]));//1 第一个元素(a)

printf("%d\n", sizeof(&p));//4 &p取的是p的地址,p是一个指针,指向a的地址,但p的地址是什么并不知道

printf("%d\n", sizeof(&p + 1));//4 &p+1--跳过了p的一个地址

printf("%d\n", sizeof(&p[0] + 1));//4 还是一个地址,这个地址指向了b的地址

printf("%d\n", strlen(p));//6 从a开始向后数

printf("%d\n", strlen(p + 1));//5 从b开始向后数

printf("%d\n", strlen(*p));//错误 *p就是a,strlen()要的是一个地址,而不是a的ASCII码值(97)

printf("%d\n", strlen(p[0]));//错误

printf("%d\n", strlen(&p));//随机值

printf("%d\n", strlen(&p + 1));//随机值

printf("%d\n", strlen(&p[0] + 1));//5 从b开始往后数

return 0;

}

210630117_14_20201221080332520

#include

//二维数组

int main()

{

int a[3][4] = { 0 };

printf("%d\n", sizeof(a));//48 整个数组有12个元素,每个元素都是int型

printf("%d\n", sizeof(a[0][0]));//4 代表的是第一行第一列那个元素

printf("%d\n", sizeof(a[0]));//16 a[0]--第一行数组名,第一行总共有4个元素

printf("%d\n", sizeof(a[0] + 1));//4 a[0]降级变为a[0][0]的地址,a[0]+1是a[0][1]的地址

printf("%d\n", sizeof(a + 1));//4 a--首元素(第一行)地址,a+1--第二行地址

printf("%d\n", sizeof(&a[0] + 1));//4 第二行地址

printf("%d\n", sizeof(*a));//16 对第一行地址解引用就是第一行元素

printf("%d\n", sizeof(a[3]));//16 这里有好多人会出错,认为这个数组并没有这么大,只有3行,不能访问第4行,其实这里并没有访问第4行,它只是一个类型(1行的大小)

return 0;

}

210630117_15_20201221080332623

11.数组作为函数参数

我们在写代码的时候,会将数组作为参数传给函数。

eg:

void bubble(int arr[])

{

int sz = sizeof(arr)/sizeof(arr[0]);//这是错误的

...

}

数组作为函数参数时,不会把整个数组传递过去,实际上只是把数组的首元素地址传递过去了。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值