IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c指针基础 -> 正文阅读

[C++知识库]c指针基础

一、指针、指针变量的引用
1.一个变量的地址称为该变量的指针
例如,地址2000是变量 i 的指针

2.一个变量专门用来存放另一变量的地址(即指针),则它称为指针变量

3.定义指针变量:
类型名 * 指针变量名
指针变量的值是地址

二、指针变量作函数参数

数组元素作实参时,参数传递具有单向性,即实参的改变可以影响形参,而形参的改变无法影响实参。

假设已经定义了一个函数,其原型为:

void swap(int x, int y);

假设函数的作用是将两个形参(x, y)的值交换,今有以下的函数调用:

swap(int a[1], int a[2]);

数组名作函数参数时,实参和形参的改变可以相互影响。因为实参数组名代表首元素的地址,而形参是用来接收从实参传递过来的数组首元素的地址的,因此形参是一个指针变量。

把变量名作为函数参数与把数组名作为函数参数相互比较,可以得到:

在这里插入图片描述

例子:
利用指针变量当形参,将数组a中的n个整数按逆序排列。
代码如下:

# include<stdio.h>

int main()
{
	void inv(int x[], int n);
	int i, a[10];

	printf("Please enter 10 integer numbers:\n");
	for(i=0;i<10;i++)
		scanf("%d", &a[i]);

	inv(a,10);
	
	printf("The array has been inverted:\n");
	for(i=0;i<10;i++)
		printf("%d ", a[i]);
	
	printf("\n");
	return 0;
}

void inv(int x[], int n)
{
	int temp, j;

	for(j=0;j<=(n-1)/2;j++)
	{
		temp = x[j];
		x[j] = x[n-j-1];
		x[n-j-1] = temp;
	}
}

运行输入数值测试:

在这里插入图片描述
这里重点注意函数的形参与指针结合使用方法。分析循环时,注意分析循环结束条件,以及在循环体中使用数组的下标与数组元素的个数、定义的变量的关系表达式。

案例2:使用指针方法给一个数组排序

实现代码:

#include "stdio.h"
void main()
{void exchange(int *q1,int *q2,int *q3);
 int a,b,c,*p1,*p2,*p3;
 scanf("%d,%d,%d",&a,&b,&c);
 p1=&a;p2=&b;p3=&c;
 exchange(p1,p2,p3);
 printf("The order is:%d,%d,%d",a,b,c);
    printf("The order is:%d,%d,%d",*p1,*p2,*p3);
    
}
void exchange(int *q1,int *q2,int *q3)
{void swap(int *m1,int *m2);
 if(*q1<*q2) swap(q1,q2);
 if(*q1<*q3) swap(q1,q3);
 if(*q2<*q3) swap(q2,q3);
}
void swap(int *m1,int *m2)
{ int t;
  t=*m1;
  *m1=*m2;
  *m2=t;
}

实现效果:

在这里插入图片描述
补充说明:这里我是使用了两种不同的输出排好序的数字的方法。
三、通过指针引用数组

引用一个数组元素,可以用以下两种方法:
1.下标法,如 a[i] 形式;
2.指针法,如 *(a+i)或 *(p+i)。其中 a 是数组名,p是指向数组元素的指针变量,其初值为 p=a;

测试案例:通过指针变量输出整型数组 a 的5个元素//指针法

代码如下:

# include<stdio.h>

int main()
{
	int i,a[5],*p;
	p=a;

	printf("Please enter 5 integer numbers:\n");
	for(i=0;i<5;i++)
		scanf("%d",p++);
	for(p=a,i=0;i<5;i++,p++)    
		printf("%d ",*p);   
	printf("\n");

	return 0;
}

运行结果

在这里插入图片描述
注意:在使用指针方法输出数组时,不能使用数组的名称作为指针变量输出,它是一个指针常量。

案例2:使用指针方法将数组中最大的数与最后一个数交换顺序,最小数与数组的第一个数(即a[0])交换顺序。

实现代码:

#include "stdio.h"
void main()
{
 void input(int a[],int size);
 void change(int a[],int size);
 void output(int a[],int size);
 int a[10];
 input(a,10);
 change(a,10);
 output(a,10);
    
}
void input(int a[],int size)
{
 int *p=a;
 for(;p<a+size;p++)
 {
  scanf("%d",p);
 }
}
void change(int a[],int size)
{
 int i,t=0;
 void exchange(int *pa,int *pb);
 for(i=0;i<size;i++)
 {
  if(*(a+t)>*(a+i))
  {
  	t=i;
  }
 }
 if(t!=0)
 {
   exchange(&a[t],&a[0]);
 }
 t=0;
 for(i=0;i<size;i++)
 {
  if(*(a+t)<*(a+i))
  {
  	t=i;
  }
 }
 if(t!=size-1)
 {
  exchange(&a[t],&a[size-1]);
 }
}
void exchange(int *pa,int *pb)
{
 int t;
 t=*pa;
 *pa=*pb;
 *pb=t;
}
void output(int a[],int size)
{
	int *p=a;
	for(p=a;p<a+size;p++)
	{
		printf("%d ",*p);
	}
}
 

运行结果:

在这里插入图片描述

四、通过指针引用多维数组

1、多维数组元素的地址
首先通过图解二维数组的行列组成结构来进一步理解指针引用多维数组

在这里插入图片描述
根据多维数组的定义以及多维数组的图解分析,可以总结出多维数组的相关指针表示形式:

在这里插入图片描述

2、指向多维数组元素的指针变量

(1)指向由m个元素组成的一维数组的指针变量
案例:

# include<stdio.h>
int main()
{
	int a[3][4] = {1,3,5,7,9,11,13,15,17,19,21,23};
	int (*p)[4], i ,j;         //指针变量 p 指向包含4个整型元素的一维数组

	p=a;                                      // p指向二维数组的0行           
	
	printf("please enter row and column:\n");
	scanf("%d,%d",&i, &j);                    //输出要求输出的元素的行列号

	printf("a[%d,%d]=%d\n", i,j,*(*(p+i)+j)); // 输出a[i][j]的值

	printf("\n");
	return 0;
}

运行效果省略.

(2)用指向数组的指针做函数参数

案例:查找一门以上课程不及格的学生,并输出其全部成绩

代码如下:

#include <stdio.h>
int main()
{
	void search(float(*p)[4],int n);
    float score[3][4]={{65,57,70,60},{58,87,90,81},{90,99,100,98}};
    search(score,3);
    return 0;
}
void search(float(*p)[4],int n)
{
  int i,j,flag;
  for(j=0;j<n;j++)
     {
       flag=0;
       for(i=0;i<4;i++)
         if(*(*(p+j)+i)<60)flag=1;
       
	   if(flag==1)
         {
			printf("NO.%d fails,his score are:\n",j+1);
			for(i=0;i<4;i++)
				printf("%5.1f",*(*(p+j)+i));
			printf("\n");
         } 
     }
}  


运行测试:

在这里插入图片描述

五、通过指针引用字符串
1、字符串的引用方式
(1)通过数组名和下标
思路:正常给字符变量赋值输出即可引用。
(2)通过指针变量
思路:定义个字符类型的指针变量,并给它赋初值。
最后输出验证。

2、字符指针做函数参数
这里还是通过一个输出字符串的案例来说明如何使用字符指针做函数参数

案例:将字符数组a中的字符串复制给字符串b,并输出验证

实现代码:

#include <stdio.h>

int main()
{
	void copy_string(char from[], char to[]);
	char a[]="I love china!";
	char b[]="You are a teacher!";

	printf("string a=%s\nstring b=%s\n",a,b);
	printf("copy string a to string b:\n");

	copy_string(a,b);

	printf("string a=%s\nstring b=%s\n",a,b);

	return 0;

}

void copy_string(char from[], char to[])
{
	int i = 0;
	while(from[i]!='\0')
		{
			to[i]=from[i];
			i++;
		}	
	to[i]='\0';		
}

这里的形参、实参都是使用了字符数组名,也可以用字符指针变量。

具体实现代码省略,参数用*from,*to代替字符数组。

六、动态内存分配

建立内存的动态分配
接下来介绍四个函数来进行动态分配内存:
1、malloc 开辟动态存储区
函数原型:void *malloc(unsigned int size);
使用说明:使用该函数在动态存储区分配一个长度为size的连续空间,unsigned为无符号整型。
2、calloc 开辟动态存储区
函数原型:void *calloc(unsigned n,unsigned int size);
使用说明:使用该函数在动态存储区分配n个长度为size的连续空间,
3、realloc 重新开辟动态存储区
函数原型:void *realloc(void *p,unsigned int size);
使用说明:在使用前两个函数开辟内存空间的前提下,使用该函数重新分配大小。
4、free 释放动态存储区域
函数原型:void *free(void *p);
使用说明:其作用是释放指针变量 p 所指向的动态空间,使这部分空间能重新被其他变量使用。p 应是最后一次调用 calloc或 malloc 函数时得到的函数返回值

注意:在编写程序时要把"stdlib.h"的头文件放在预处理行的位置中

下面举一个复杂的例子来说明以上函数的用法
案例:通过创建动态链表输出学生的所有信息,其中学生信息定义一个结构体类型存放。

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
struct Student{
  int num;
  char name [20];
  int age;
}; 
struct Node{
  struct Student stu;
  struct Node *next;
};
void main()
{struct Node *head,*p,*n;
 int i;
 n=(struct Node *)malloc(sizeof(struct Node));
 (*n).stu.num=10010;
 strcpy((*n).stu.name,"wang");
 (*n).stu.age=13;
 (*n).next=NULL;
 p=n;
 head=n;
 for(i=0;i<2;i++)
 {
   n=(struct Node *)malloc(sizeof(struct Node));
   scanf("%d%s%d",&((*n).stu.num),&((*n).stu.name),&((*n).stu.age));
   (*n).next=NULL;
   p->next=n;
   p=n;
 }
 printf("\n");
 for(p=head;p!=NULL;p=p->next)
 {
   printf("%d %s %d\n",(*p).stu.num,(*p).stu.name,(*p).stu.age);
 }
}

输入值测试 运行结果:
在这里插入图片描述

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-14 15:45:21  更:2021-12-14 15:47:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:44:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码