C语言

您所在的位置:网站首页 三维数组的定义及数组元素的访问方法。主 C语言

C语言

2024-07-13 21:45| 来源: 网络整理| 查看: 265

指针相关概念

操作系统给每个存储单元分配了一个编号,从 0x00 00 00 00 ~ 0xff ff ff ff,这个编号就称之为地址,指针就是地址。

指针变量:是个变量,是个指针变量,即这个变量存放一个地址编号。在32位平台下,地址总线是32位的,所以地址是32位编号,所以指针变量是32位的即4个字节。

注意:

1、无论什么类型的地址,都是存储单元的编号,在32位平台下都是4个字节,即任何类型的指针变量都是4个字节大小。

2、对应类型的指针变量,只能存放对应类型的变量地址。例如:整型的指针变量,只能存放整型变量的地址。

扩展:字符变量 char ch;ch占1个字节,他有一个地址编号,这个地址编号就是ch的地址;整型变量 int a;a占4个字节,它占有4个字节的存储单元,有4个地址编号。

指针定义方法

1、简单的指针

数据类型 * 指针变量名;int *p;//定义了一个指针变量p

在定义指针变量的时候 * 是用来修饰变量的,说明变量 p 是个指针变量,变量名是 p。

2、关于指针的运算符:& 取地址、*取值

注意:如果在一行定义多个指针变量,每个指针变量前面都需要加 * 来修饰,中间用逗号分隔;若不加 * 则是普通的变量。

指针分类

1、字符指针

字符型数据的地址

char *p;//定义一个字符指针变量,只能存放字符型数据的地址编号 char ch; p = &ch;//p存放ch的地址

2、短整型指针

short int *p;//定义了一个短整型的指针变量p,只能存放短整型变量的地址 short int a; p = &a;

3、整型指针

int *p;//定义了一个整型的指针变量p,只能存放整型变量的地址 int a; p = &a;

4、长整型指针

long int *p;//定义了一个长整型指针变量p,只能存放长整型变量地址 long int a; p = &a;

5、float型的指针

float *p;//定义了一个float型指针变量p,只能存放float型变量的指针 float a; p = &a

6、double型的指针

double *p;//定义了一个double型的指针变量p,只能存放double型变量的地址 double a; p = &a;

7、函数指针

8、结构体指针

9、指针的指针

10、数组指针

注意:无论什么类型的指针变量,在32位系统下,都是4个字节,只能存放对应类型的变量的地址编号。

指针和变量关系

可以 通过指针变量来引用变量

int *p;//在定义的时候,*不是取值的意思,而是修饰的意思,修饰p是个指针 p = &a;//去a的地址给p赋值,p保存了a的地址,也可以说p指向了a *p = 100;//在调用的时候*是取值的意思,*指针变量等价于指针指向的变量

注意:指针变量在定义的时候可以初始化

int a; int *p =&a;//用a的地址,给p赋值,因为p是指针变量

指针就是用来存放变量的地址的。*+指针变量就相当于指针指向的变量。

注意:对应类型的指针,只能保存对应类型数据的地址,如果想让不同类型的指针相互赋值的时候,需要强制类型转换

注意:1、*+指针 取值的意思,取几个字节,由指针类型决定的指针为字符指针则取一个字节,指针为整型指针则取4个字节,指针为double型指针则取8个字节。

2、指针++ 指向下个对应的数据

字符指针++,指向下个字符数据,指针存放的地址编号加1;整型指针++,指向下一个整型数据,指针存放的地址编号加4。

指针和数组之间的关系 数组引用方法:指针名加下标 int a[10]; int *p; p = a; p[2] = 100;//因为p和a等价

C语言规定:数组的名字就是数组的首地址,即第0个元素的地址,是个常量。

注意:p和a的不同,p是指针变量,而a是个常量。所以可以用等号给p赋值,但不能给a赋值。

通过指针运算加取值的方法引用数组的元素 int a[10]; int *p; p=a; *(p+2)=100;//也是可以的,相当于a[2]=100

p是第0个元素的地址,p+2是a[2]这个元素的地址。对第二个元素的地址取值,即a[2]

指针的运算

1、指针可以加一个整数,往下值几个它指向的变量,结果还是个地址

前提:指针指向数组的时候,加一个整数才有意义。

2、两个相同类型指针可以比较大小

前提:只有两个相同类型的指针指向同一个数组的时候,比较大小才有意义。

指向前面元素的指针 小于 指向后面元素的指针

3、两个相同的指针可以做减法

前提:必须是两个相同的指针指向同一个数组元素的时候,做减法才有意义。

做减法的结果是,两个指针指向的中间有多少个元素。

4、两个相同类型的指针可以相互赋值

注意:只有相同类型的指针才可以相互赋值(void*类型的除外,通用指针)

int *p; int *q; int = a; p=&a;//p保存a的地址,p指向了变量a q=p;//用p给q赋值,q也保存了a的地址,指向a

注意:如果类型不相同的指针要想相互赋值,不需进行强制类型转换

指针数组

1、指针和数组的关系

1:指针可以保存数组元素的地址

2:可以定义一个数组,数组中有若干个相同类型指针变量,这个数组被称为指针数组

指针数组的概念:其本身是个数组,是个指针数组,是如干个相同类型的指针变量构成的集合

2、指针数组的定义方法

类型说明符 * 数组名[元素个数]; int *p[10];//定义了一个整型的指针数组p,有10个元素p[0]~p[9],每个元素都是 int*类型的变量

3、指针数组分类

字符指针数组、短整型指针数组、整型的指针数组、长整型指针数组、float型的指针数组、double型的指针数组、结构体指针数组、函数指针数组

指针的指针

指针的指针,即指针的地址,定义一个指针变量本身指针占4个字节,指针变量也有地址编号

注意:指针指向的内存能不能被修改,要看指针指向哪里。指向文字常量区的时候,内存里的内容不可修改,指向栈、堆、静态全局区的时候,内存的内容是可以修改。

#栈和全局内存中的内容是可以修改 char str[100]="I love C!"; str[0]='y';//正确,可以修改 #文字常量区里的内容是不可以修改的 char *str="I love C!"; *str='y';//错误,I存放在文字常量区,不可修改 #堆区的内容可以修改 char *=(char*)malloc(10*size(char)); strcpy(str,"I love C"); *str='y';//正确,可以修改,因为堆区内容是可以修改 初始化

字符数组、指针指向的字符串:定义时直接初始化

char buf_aver[]="hello world"; char*buf_point="hello word";

堆中存放的字符串不能初始化、只能使用 strcpy、scanf 赋值

char *buf_heap; buf_heap=(char*)malloc(15); strcpy(buf_heap,"hello word"); scanf("%s",buf_heap); 使用时赋值

字符数组:使用scanf 或者 strcoy

buf_aver="hello kitty";//错误,因为字符数组的名字是个常量 strcpy(buf_aver,"hello word");//正确 scanf("%s",buf_aver);//正确

指向字符串的指针:

buf_point="hell kitty";//正确,buf_point指向另一个字符串 strcpy(buf_point,"hello kitty");//错误,只读,能不能复制字符串到buf_point指向的内存里取决于buf_point指向哪里

字符串和指针

数组指针

概念:是个指针。指向一个数组,加1跳一个数组,即指向下一个数组。

定义

指向的数组的类型(*指针变量名)[指向的数组的元素个数] int (*p)[5];//定义了一个数组指针变量p,p指向的是整型的有5个元素的数组 p+1 往下指5个整型,跳过一个有5个整型元素的数组。 数组指针和指针数组 int (*p)[5];//数组指针, //本身是个指针变量,p占4个字节,用来保存数组的地址 int *p[5];//指针数组 //本身是个数组,是由5个int *类型的指针元素构成的指针数组 数组名字取地址:变成 数组指针

一维数组名字取地址,变成一维数组指针,即加 1 跳一个一维数组

int a[10]; //a+1 跳一个整型元素,是a[1]的地址 //a和a+1相差一个元素,4个字节 //&a就变成了一个一维数组指针,是int(*p)[10]类型的。 //(&a)+1和&a相差一个数组,即10个元素,即40个字节。 数组名字和指针变量的区别 int a[10]; int*p; p=a;

相同点:

a是数组的名字,是a[0]的地址,p=a即p也保存了a[0]的地址,即a和p都指向a[0],所以在引用数组元素的时候,a和p等价。引用数组元素:a[2]、*(a+2)、p[2]、*(p+2)都是对数组a中a[2]元素的引用。

不同点:

1、a是常量、p是变量,可以用等号"="给p赋值,但不能用等号给a赋值

2、对a取地址,和对p取地址结果不同,因为a是数组的名字,所以对a取地址结果为数组指针。p是个指针变量,所以对p取地址(&p)结果为指针的指针。

多维数组中指针的转换

在二维数组中,行地址去 * 不是取值的意思,而是指针降级的意思,由行地址(数组指针)变成这一行第 0 个元素的地址。取*前后还是指向同一个地方,但是指针的类型不一样了。

int a[3][5]; printf("a=%p\n",a);//第0行的地址 printf("a+1=%p\n",a+1);// printf("*a=%p\n",*a);//*a变成了第0行第0列元素的地址 printf("(*a)+1=%p\n",(*a)+1);//结果为第0行第1列元素的地址 指针和函数的关系

1、指针作为函数的参数

可以给一个函数传一个 整型、字符型、浮点型的数据,也可以给函数传一个地址。

int num; scanf("%d",&num) 函数传参

1、传数值:

void swap(int x,int y) { int temp; temp=x; x=y; y=temp; } int main() { int a=10,b=20; swap(a,b); printf("a=%d b=%d\n",a,b); }

实参:调用函数时传的参数。

形参:定义被调函数时,函数名后边括号里的数据

结论:给被调函数传数值,只能改变被调函数形参的值,不能改变主调函数实参的值。

2、传地址

void swap(int *p1,int *p2) { int temp; temp=*p1; *p1=*p2; //p2指向的变量的值,给p1指向的变量赋值 *p2=temp; } int main() { int a=10,b=20; swap(&a,&b); printf("a=%d b=%d\n",a,b);//结果为a=20 b=10 }

结论:调用函数的时候传变量的地址,在被调函数中通过 *+地址来改变主调函数中的变量的值。

void swap(int *p1,int *p2)//&a &b { int *p; p=p1; p1=p2;//p1=&b让p1指向main中的b p2=p;//让p2指向main函数中a }//此函数中改变的是p1和p2的指向,并没有给main中的a和b赋值 int main() { int a=10,b=20; swap(&a,&b); printf("a=%d b=%d\n",a,b);//结果为a=10,b=20 }

总结:要想改变主调函数中变量的值,必须传变量的地址,而且还得通过 *+地址 去赋值。无论这个变量是什么类型的。

3、传数组

给函数传数组的时候,没法一下将数组的内容作为整体传出去。只能传数组的地址。

//传一维数组的地址 //void fun(int p[])//形式1 void fun(int *p)//形式2 { printf("%d\n",p[2]); printf("%d\n",*p(p+3)); } int main() { int a[10]={1,2,3,4,5,6,7,8,9}; fun(a); } //传二维数组 //void fun(int p[][4])//形式1 void fun(int (*p)[4])//形式2 { } int main() { int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}; fun(a); rturn 0; } //传指针数组 void fun(char **q)//char *q[] { int i; for(i=0;i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3