数组和指针
2023-08-19 09:50:52 2 举报
AI智能生成
数组和指针的知识点
作者其他创作
大纲/内容
数组
概念
具有一定顺序的若干变量的集合
分类
一维数组
定义
存储类型 数据类型 数组名[元素的个数]
数组名:代表数组的首地址
地址常量:不可以被重新赋值,不能为左值,不可以进行++ --的操作
数组中的每一项都是变量,称之为元素
地址常量:不可以被重新赋值,不能为左值,不可以进行++ --的操作
数组中的每一项都是变量,称之为元素
数组更新
访问元素:数组名[元素的下标],下标从零开始
访问第一个元素arr[0],访问第N个元素arr[N-1]
注意数组越界的问题,会有修改别的变量的风险,原变量的值会被覆盖
修改元素的内容:数组名[元素的下标] = 新值
访问第一个元素arr[0],访问第N个元素arr[N-1]
注意数组越界的问题,会有修改别的变量的风险,原变量的值会被覆盖
修改元素的内容:数组名[元素的下标] = 新值
特点
数组的类型要和后面存储的数据的数据类型相同
内存地址是连续的
定义数组时遵循标识符的命名规则
数组下标从零开始,有N'个元素,下标到N-1
在同一个函数中,数组名和变量名不能重名
初始化
全部初始化
int a[3] = {1,2,3};
部分初始化
int a[3] = {1,2};
未赋值的元素值为0
未初始化
int a[3];
未赋值的元素值为随机数
数组遍历
int a[N] = {0,1……,N};
int i;
for(i = 0;i < N;i++)
{
printf("%d",a[i]);
}
int i;
for(i = 0;i < N;i++)
{
printf("%d",a[i]);
}
数组的输入输出
scanf
printf
gets
功能:从终端输入一个字符串
参数:字符数组的首地址
返回值:目标字符串的首地址
注意:使用gets的时候要注意关心数组越界的问题,使用时会报警告不要在意,不影响运行
puts
功能:向终端输出一个字符串
参数:要输出的字符数组的首地址
返回值:输出字符的个数
数组的大小
元素的个数*数据类型的大小
sizeof()
int arr[5];
printf("%d\n",sizeof(arr));
int arr[5];
printf("%d\n",sizeof(arr));
数组元素的个数
数组的大小/数据类型的大小
sizeof(数组名)/sizeof(数据类型)
sizeof(数组名)/sizeof(数据类型)
清空函数
bzero:
#include <strings.h>
void bzero(void *s, size_t n);
#include <strings.h>
void bzero(void *s, size_t n);
功能:将内存空间设置为0
参数:s:需要清空空间的首地址
n:需要清空空间的字节大小
n:需要清空空间的字节大小
返回值:无
memset:
#include <string.h>
void *memset(void *s, int c, size_t n);
#include <string.h>
void *memset(void *s, int c, size_t n);
功能:将内存空间设置为0
参数:s:需要清空空间的首地址
c:将空间设置成的大小,默认是写0,设置成其他的不准确
n:需要清空空间的字节大小
c:将空间设置成的大小,默认是写0,设置成其他的不准确
n:需要清空空间的字节大小
返回值:清空空间后的首地址
字符数组
概念:用来存放若干字符的集合(存放字符串),数据类型是char类型
注意:在定义字符数组时,经常省略元素的个数,需要注意数组越界
字符的输入输出
for循环,打印格式用%c
可以使用%[^\n]直到遇到\n,才理解为结束
char a[32];
int i;
scanf("%[^\n]",a);
printf("%s\n",a);
可以使用%[^\n]直到遇到\n,才理解为结束
char a[32];
int i;
scanf("%[^\n]",a);
printf("%s\n",a);
字符数组计算字符个数(字符数组的实际长度)
for循环,将判断条件设置为不等于\0进行计数加1
sizeof(数组名)/sizeof(数据类型)
sizeof(数组名)-1
sizeof(数组名)/sizeof(数据类型)
sizeof(数组名)-1
stelen:
#include <string.h>
size_t strlen(const char *s);
#include <string.h>
size_t strlen(const char *s);
功能:计算字符串实际长度
参数:s:字符串的首地址
返回值:字符串的实际长度
sizeof和strlen的区别
sizeof是一个关键字,strlen是一个函数
sizeof作用是用来计算数据所占空间的大小,strlen是用来计算字符串的实际长度
sizeof计算时包含\0,但是strlen不包含
排序
双重循环 外层控制轮数i,内层循环比较次数j
双重循环 外层控制轮数i,内层循环比较次数j
冒泡排序
两两进行比较,相邻的两个数进行比较
特点:第一轮比较完成之后最大值在最后面
选择排序
在N个数中找最小值,标记下标
特点:第一轮结束之后最小值在最前面
二维数组
格式:存储类型 数据类型 数组名[行数][列数]
int arr [][3];可以省略行数,但是不能省略列数
int arr [][3];可以省略行数,但是不能省略列数
访问元素:数组名[行下标][列下标]
元素的个数:行数*列数
数组大小:行数*列数*数据类型的大小
sizeof(数组名)
sizeof(数组名)
初始化
全部初始化
int arr[2][3] = {1,2,3,4,5,6};按照顺序赋值
int arr[2][3] = {1,2,3},{4,5,6};按照行进行赋值
int arr[2][3] = {1,2,3},{4,5,6};按照行进行赋值
部分初始化
int arr[2][3] = {1,2,3,4};按照顺序赋值1,2,3,4,0,0
int arr[2][3] = {1,2},{4};按照行进行赋值1,2,0,4,0,0
int arr[2][3] = {1,2},{4};按照行进行赋值1,2,0,4,0,0
未初始化
只能一个元素一个元素的赋值,未赋值的是随机数
int arr[2][3];
a[0][0] = 1;
int arr[2][3];
a[0][0] = 1;
二维数组的遍历
for的嵌套,外层循环控制行数,内层循环控制列数
输入输出
字符串可以直接按行输出
char arr[2][6] = {i,hello,china};按照顺序赋值
printf("%s %s %s",a[2],a[1],a[0]);
char arr[2][6] = {i,hello,china};按照顺序赋值
printf("%s %s %s",a[2],a[1],a[0]);
指针数组
定义:本质是一个数组,存放指针
格式:存储类型 数据类型 *指针数组名[元素的个数]
使用场景
存放普通变量的地址
int a=10,b=20,c=30;
int *p[3] = {&a,&b,&c};
//访问b的值:*p[1] *(*(p+1))
//访问c的地址:p[2] *(p+2)
int *p[3] = {&a,&b,&c};
//访问b的值:*p[1] *(*(p+1))
//访问c的地址:p[2] *(p+2)
可以存放二维数组的地址
存放二维数组的每一行的首地址
存放二维数组的每一行的首地址
int a[2][3] = {1,2,3,4,5,6};
int *p[2] = {a[0],a[1]};
//访问a[1][2]的值:*(p[1]+2) *(*(p+1)+2)
//访问a[1][2]的地址:p[1]+2 *(p+1)+2
int *p[2] = {a[0],a[1]};
//访问a[1][2]的值:*(p[1]+2) *(*(p+1)+2)
//访问a[1][2]的地址:p[1]+2 *(p+1)+2
存放字符串
char *p[3] = {"hello","world","hqyj"};
//访问world字符串:%s格式 p[1] *(p+1)
//访问e字符:%c格式 p[0][1] *(p[0]+1)
//访问world字符串:%s格式 p[1] *(p+1)
//访问e字符:%c格式 p[0][1] *(p[0]+1)
命令行参数
argc:argv数组中元素的个数
argv:指针数组,用来接收命令行中所有参数
*argv[i]是指针数组,相当于二维数组,所以*argv[i]表示二维数组各行的的首地址
指针
就是地址,内存的地址
地址:内存当中的每个字节都是一个单元格,每个单元格都有一个编号
指针变量:用来存储指针的变量
定义格式:存储类型 数据类型 *指针变量名
注意:定义指针的数据类型和将要存储的数据的数据类型保持一致
指针的操作符
&:取地址符,取变量的地址
*:取内容符,对地址进行取内容
指针和指针所指的变量之间的关系
int a = 20;
int *p = &a;
printf("%d %d\n",a,*p);
printf("%p %p\n",&a,p);
printf("%p\n",&p);
int *p = &a;
printf("%d %d\n",a,*p);
printf("%p %p\n",&a,p);
printf("%p\n",&p);
指针的初始化
将普通变量的地址赋值给指针
将数组的首地址赋值给指针
将指针变量的内容赋值给另一个指针
指针的运算
算数运算+ - ++ --
p+1:向高地址位置移动一个数据单位,但是指针p的指向并不会发生时改变
p-1:向低地址位置移动一个数据单位,但是指针p的指向并不会发生时改变
p-1:向低地址位置移动一个数据单位,但是指针p的指向并不会发生时改变
++p:向高地址位置移动一个数据单位,同时改变指针p的指向
--p:向低地址位置移动一个数据单位,同时改变指针p的指向
--p:向低地址位置移动一个数据单位,同时改变指针p的指向
p++:向高地址位置移动一个数据单位,先运算(输出 或者计算)后移动指向,改变指针p的指向
p--:向低地址位置移动一个数据单位,先运算(输出 或者计算)后移动指向
p--:向低地址位置移动一个数据单位,先运算(输出 或者计算)后移动指向
关系运算> < == !=
指针之间比较大小始终指向高地址的指针大
注意:指针之间的比较时必须是同一区域的比较(同一个数组之间进行比较),非同一区域的比较是没有意义的
指针的大小
指针的大小取决于操作系统,64位操作系统,指针占8个字节,32位操作系统占4个字节,1个字节是8位
总结
1.指针的大小取决于操作系统,32位的操作系统就是4个字节
2.内存地址是固定的,但是变量的地址是不固定的,栈区的地址是随机分配的
3.指针的数据类型是他指向的空间的数据类型决定
2.内存地址是固定的,但是变量的地址是不固定的,栈区的地址是随机分配的
3.指针的数据类型是他指向的空间的数据类型决定
段错误
野指针
定义了一个指针没有初始化
解决:给指针赋值,或赋值为NULL
内存泄漏
对非法空间进行操作
指针修饰
const常量化
只要被const修饰的内容就是一个只读,不可以被修改
修饰变量
const int a = 10;//a就不能被修改
或者
int const a = 10;
a不可以修改,但是可以通过间接修改的方式修改掉a的值,通过指针修改
const int a = 10;//a就不能被修改
或者
int const a = 10;
a不可以修改,但是可以通过间接修改的方式修改掉a的值,通过指针修改
修饰指针*p
const int *p;//修饰p不可以被修改
const int *p;//修饰p不可以被修改
修饰指针p
int *const p = &a;指针的指向不能被修改
int *const p = &a;指针的指向不能被修改
二级指针
概念:二级指针是用来存储一级指针的地址
格式:存储类型 数据类型 **指针变量;
指针和数组
指针和一维数组
访问数组的元素a[i]的值
直接访问:a[i] *(a+i)
间接访问:p[i] *(p+i)
访问数组的元素a[i]的地址
直接访问:&a[i] a+i
间接访问:&p[i] p+i
注意
a和p本质是不同的,a是数组名代表数组的首地址,是地址常量,不可以被修改
指针p是一个变量,可以被修改
指针p是一个变量,可以被修改
指针和二维数组
直接访问
访问二维数组a[i][j]的值
a[i][j] *(*(a+i)+j) *(a[i]+j)
访问二维数组a[i][j]的地址
&a[i][j] *(a+i)+j a[i]+j
间接访问
访问二维数组a[i][j]的值
p[i][j] *(*(p+i)+j) *(p[i]+j)
访问二维数组a[i][j]的地址
*(p+i)+j p[i]+j &p[i][j]
数组指针
定义:本质还是指针,指向数组(行指针)
地址是行地址
格式:存储类型 数据类型 (*指针变量名)[列数]
数组指针的大小
sizeof(数组指针名)= 4字节 取决于操作系统
0 条评论
下一页