动手学习C语言-实参和形参均为指针变量

指针变量

本质:指针是已定义的数据变量的存放地址;该地址就是访问该变量的内存地址;
指针变量是用来存放数据变量地址的内存变量。通过取地址运算的赋值操作后,将使该指针变量指向那个被取出地址的数据变量;
指针变量一般即称:指针;
指针的内容:就是各种已定义数据类型操作对象的内存地址;

// 比较直接访问与间接访问数据变量的 操作方式
// 比较直接访问与间接访问数据变量的 操作方式

#include "stdio.h"
void main(){
	int i=20;
	int m,n;
	int* i_pointer =&i;

	m=i+6;     //直接访问变量i数据值
	n=*i_pointer+3;  // 间接访问i,通过指针

	i_pointer=&m;   // 指针指向m变量

	printf("m=%d \nn=%d \n",*i_pointer,n);  // m 是通过间接访问,n 直接访问

}

指针就是存放如下内存地址的变量;变量名相当于是引用(取外号小名);

指针变量的赋值

指针变量的赋值:只能是赋予已定义变量的地址值 ,而不能赋予任何其他数据;
C语言提供了地址运算符“&”来表示和执行变量地址的运算;
变量地址运算的一般形式为: &变量名; Eg: &number 为:运算结果为变量number的地址;
注意:像符号 “*”和“&”都具有多义性,即在不同的环境下表示的语法含义不同
指针变量定义初始化操作:
int number;
int* p=&number;
等价于:
int number;
int* p;
p=&number;

指针变量运算符及运算

地址变量运算符: “&”:取地址运算符 ;“*”:变量值存取运算符;
可能形式:&*pointer 运算,等效于 &(pointer):结果还是pointer对应的内存地址;
(&x)运算–等效于(&x):结果是对应的x变量值;
pointer)++,相当于x++;
pointer++,等效于
(pointer++);
// 简单小例子
// 指针变量运算符及运算

#include "stdio.h"

void main(){
		int a=10,b=20;
		int* pointer =&a;  // pointer指向a
		a=*pointer+5;

		pointer=&b;   //pointer指向b;
		b=*pointer +a;

		printf("a is %d,b is %d \n",a,*pointer);
		printf("b address is %d \n",pointer);

	
}

指针变量运算

Eg1:
int x;
int* px=&x;
int* pb;
pb=px;
Eg2:
int x[5],*px;
px=x;数组名就是首地址;
Eg3:
char *pc;
pc=“c language” // 即为把字符串的首地址赋值给pc;

2、加减运算符
指针的加减运算符对于单个变量没有意义,主要是对于指向数组或链表的指针变量;加减运算符运算按数据类型长度为单位;
int x[5];
int* px;
px=x; // px指向数组x的首地址,即指向数组元素x[0]的地址
px=px+2; // px指向x[2]的地址,即px的值为&x[2]的地址

3、空指针运算
空指针p=NULL表示指针变量p不指向任何数据变量;
if(p=NULL) …
注意:空指针与指针未赋值是不同的;空指针p=NULL,等价于看做值为NULL,不指向任何变量的指针变量,但是未赋值的指针,无指向且地址值不定,有可能随机指向而破坏系统;所以指针一旦定义必须被赋值初始化,使其有所指向

指针变量作为函数参数

指针变量作为函数参数,是将变量的地址传到另一函数参数,是对变量数据的实际操作,因为传递的是指向数据变量的地址,所有可以操作实际变量的数据值,但是本身 实际指针参数和形式指针参数没有关系,还是属于单向传递;
// 编写程序,任意输入两个数,通过函数调用来交换两个变量值;
// 指针变量作为函数参数传递,操作实际变量

扫描二维码关注公众号,回复: 9813458 查看本文章
#include "stdio.h"
#include "string.h"

void swop(int* pa,int* pb);
void main(){
	int a,b;
	
	int* pa=&a;
	int* pb=&b;

	char str[]="请输入两个数:";
	puts(str);
	
	scanf("%d %d",&a,&b);
	printf("before the swop is %d,%d",a,b);
	putchar('\n');
	// 交换两个函数
	swop(pa,pb);

	printf("after the swop is %d,%d \n",a,b);

}

void swop(int* pa,int* pb){
	int temp;
	temp=*pa;
	*pa=*pb;
	*pb=temp;

}

实参变量值交换过程:

由数据变量改为指针变量

// 将上述程序中的Swap()函数里的局部变量temp,由数据变量改为指针变量;差别

void swop(int* pa,int* pb){
	int* temp;
	temp=pa;
	pa=pb;
	pb=temp;

}  // 结果这两个数是没有改变的,因为这只是交换了形式参数的指针地址而已;如下图所示;
 

这些问题很好?
1、程序运行时,计算机内存区域是如何进行划分的?
2、访问内存变量时,内存变量地址和该地址下的内存变量存储单元中的数据,在存储访问上是如何操作和实现的?
3、讨论直接访问与间接访问内存变量数据方式有何不同?
4、讨论如何获得已定义变量的地址,又是如何按该地址存放变量数据的?
5、讨论指针运算有哪些实际有效的地址操作运算符,各自操作的物理特性有哪些?
6、讨论函数参数为指针类型时,传递的是指定变量的什么内容?

由指针变量传地址改为数据变量传数据

// 指针变量作为函数参数传递,操作实际变量

#include "stdio.h"
#include "string.h"

void swop(int x,int y);
void main(){
	int a,b;
	
	int* pa=&a;
	int* pb=&b;

	char str[]="请输入两个数:";
	puts(str);
	
	scanf("%d %d",&a,&b);
	printf("before the swop is %d,%d",a,b);
	putchar('\n');
	// 交换两个函数
	swop(a,b);

	printf("after the swop is %d,%d \n",a,b);

}

void swop(int x,int y){
	int temp;
	temp=x;
	x=y;
	y=temp;

}

// 结果也是没有发生改变

形参变量值交换过程:单向传递过程

数据变量名在被定义的的时候,就永远和那个被分配好的内存地址绑定在一块了,而不是相等,代表的是该内存上的数据变量值,值可以任意改变,但变量名不变和内存地址不变;
** 数据变量名 代表:容器; 内存地址 代表:出厂编号位置;指针变量代表: 记录本记录编号
*int x=100; int p=&x; x++;(*p)++; p++// 结果:102,这时候指针p 就不指向x 了;

数组与地址指针

数组是由连续内存存储的数组元素组成;数组名就是该数组的首地址,即array[0];
数组元素引用方式:
1、下表法:array[2] 2、指针法:*(p+2);
// 编写程序,使用下表法和指针法
指针法:

数组与地址指针两种方式,来表达数组

// 数组下标法
/*#include "stdio.h"

void main(){

	// 定义变量区
	int a[6];
	int i=0;
	
	printf("请输入6个数:");
	for(i=0;i<6;i++){
		scanf("%d",&a[i]);
	}
	printf("\n");
	// 输出数组
	printf("数组输出:");
	for(i=0;i<6;i++){  // 这个圆括号里面的分号 是真的很难找啊
		printf("%3d",a[i]);
	}
	printf("\n");
	
	

}
*/

// 使用指针法
#include "stdio.h"
void main(){
	// 定义变量区
	int a[6];
	int i;
	int* p=a;
	
	//输入数据区
	printf("请输入6个数:");
	for(p=a;p<a+6;p++){
		scanf("%d",p); // 指针变量本身就是地址,不需要再去取它的地址
	}

	// 输出数组
	printf("该数组是:");
	p=a;
	for(i=0;i<6;i++){
		
		printf("%3d",*p);
		p++;
	}
	printf("\n");
}

数组名作函数参数

// 将数组x中的数组元素逆序存放
// 将数组名作函数参数,将数组中的元素逆序存放

#include "stdio.h"

#define N 5

int swop(int y[]);

void main(){
	// 定义变量区
	int a[N]; // 定义实参数组
	int i;

	//定义数组1-5;并输出	
	for(i=0;i<N;i++){
		a[i]=i+1;
	}

	printf("the array is:");
	for(i=0;i<N;i++){
		printf(" %-3d",a[i]);
	}
	printf("\n");
	
	// 数组逆序存放
	swop(a);
	// 输出
	printf("after the swop:\n");
	printf("the array is:");
	for(i=0;i<N;i++){
		printf("%-3d",a[i]);
	}
	printf("\n");
}

int swop(int y[]){  //  或者在这定义一个指针变量 
	int i=0;
	int* p=y;
	int temp;
	for(i=0;i<N/2;i++){
		temp=*(p+i);
		*(p+i)=*(p+N-1-i);
		*(p+N-1-i)=temp;
	}
	return 0;
} 

指向数组的指针变量作函数参数

指针变量可以指向地址,指针变量作为函数的参数指向数组,实现地址数据的传递
数组和指针变量传递 数组地址的方式:
// 实参和形参均使用 指针变量

// 实参和形参均使用 指针变量

#include "stdio.h"

#define N 5

int doubled(int* p); // 声明函数

void main(){

	int x[N]; // 定义数组
	int i =0; // 循环指针
	
	printf("输入这个数组:");
	// 
	for(i=0;i<N;i++){
		printf("x[%d]=",i);
		scanf("%d",x+i); // x 是首地址
	}

	printf("the array is : \n");

	for(i=0;i<N;i++){
		printf("x[%d]= %-3d ",i,*(x+i)); // 取数值
	}
	printf("after doubled is:\n");
	doubled(x);
	// 输出数组
	for(i=0;i<N;i++){
		printf("x[%d]=%-3d",i,*(x+i));
		
	}
	printf("\n");
	
}

int doubled(int* p){
	int i;
	for(i=0;i<N;i++){
		*(p+i)=*(p+i)*2;
	}
	return 0;
}
		;

多维数组与指针变量

二维数组与指针变量的 对应关系:

指针的指针:二级指针;
实际中:主要用到的就是:一级指针和二级指针

int a =100;
int p1 = &a;
int p2 = &p1;
指针变量也是一种变量,也会占用存储空间,也可以使用&获取它的地址。C语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号
。p1 是一级指针,指向普通类型的数据,定义时有一个
;p2 是二级指针,指向一级指针 p1,定义时有两个

使用指针遍历二维数组 ----->来自C语言中文网

#include <stdio.h>
int main(){
    int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
    int(*p)[4]; // 表示p+1直接跳2*4个字节直接到下一行首地址
    int i,j;
    p=a;
    for(i=0; i<3; i++){
        for(j=0; j<4; j++) printf("%2d  ",*(*(p+i)+j));
        printf("\n");
    }

    return 0;
}

指针变量指向行 输出二维矩阵

// 使用指针变量输出二维数组

#include "stdio.h"
void main(){
	// 定义变量区
	int a[2][3]= {{1,2,3},{4,5,6}};
	int (*p)[3]; // 这是定义指向一维数组的指针变量,这样定义基本上就是二维数组;int* p[3]:这是定义一维指针数组,数组元素是指针
	int i;
	int j;

	p=a;     // 指向行
	
	for(i=0;i<2;i++){
		for(j=0;j<3;j++){
			printf("%-3d",*(*(p+i)+j)); // 这还是一级指针,*(p+i)实际上一行,只是在这地方当成行的首地址

		}
		printf("\n");
	}

	printf("a[%d][%d]=%d \n",i-1,j-1,*(*(p+1)+2)); 

}

理解多维数组的编址方式和访问数组元素的特点。
使用地址方式处理二维数组运算,用什么方式访问和处理数组元素数据。

基本方式使用指针访问二维数组

// 使用指针变量输出二维数组
/*#include "stdio.h"
void main(){
	// 定义变量区
	int a[2][3]= {{1,2,3},{4,5,6}};
	int (*p)[3]; // 这是定义指向一维数组的指针变量,这样定义基本上就是二维数组;int* p[3]:这是定义一维指针数组,数组元素是指针
	int i;
	int j;

	p=a;     // 指向行
	
	for(i=0;i<2;i++){
		for(j=0;j<3;j++){
			printf("%-3d",*(*(p+i)+j)); // 这还是一级指针,*(p+i)实际上一行,只是在这地方当成行的首地址

		}
		printf("\n");
	}

	printf("a[%d][%d]=%d \n",i-1,j-1,*(*(p+1)+2)); 

}*/

// 使用另一种指针变量来操作二维数组
#include "stdio.h"
void main(){
	// 定义变量区
	int a[2][3]={{1,2,3},{4,5,6}};
	int i;
	int* p;

	p=&a[0][0];// 或者p=a[0],或者p=*a,指向二维数组首地址
	for(i=0;i<6;i++){
		if((p-a[0]) %3==0 && p!=a[0]){
			printf("\n");
		}
		printf("%-5d",*p++);
	}
	printf("\n");


}

在二维数组中,若需要计算指定数组元素位置,就需要计算该元素在数组中,相对于数组首地址的偏移量,即相对位置;
设数组array[m][n],则计算元素array[i][j]在数组中的相对位置的公式:
i*m+j; 即为 (p+im+j);

发布了39 篇原创文章 · 获赞 3 · 访问量 2503

猜你喜欢

转载自blog.csdn.net/li_kin/article/details/104835956
今日推荐