C语言指针:一维数组指针、二维数组指针、函数指针、指针函数

本文深入讲解了C语言中的指针,包括指针变量、一般数据指针、一维数组指针、二维数组指针的用法,并通过实例展示了指针在数组和字符串操作中的应用。此外,还提到了指针数组和字符串指针数组的概念。文中还讨论了函数指针以及使用指针时可能出现的问题,如未分配内存和越界访问。最后,介绍了如何从地址读取半字和字节数据。
摘要由CSDN通过智能技术生成

C语言指针学习

前言

1、指针变量是用来存储数据所在地址的。
2、变量名、函数名、字符串名和数组名在本质上是一样的,它们都是地址的助记符。
3、* 在 char *p; 中表示定义指针变量,在 *p=5; 中表示指针p指向地址中的值;“&”运算符表示取变量地址。

1. 一般数据指针

int a=5, *p;
p=&a; //表示将变量a数据存储的地址赋给指针变量p

推广:
a=*p; // 此处 * 表示解引用,即取存储在地址p 中的数值
即有:a=5,*p=5;

例:

#include <stdio.h>
void main()
{
	int a=5,*p;
	p=&a;
	printf("a=%d, *p=%d\n",a,*p);//输出数值
	printf("%x, %x\n",&a,p);//输出地址
}

运行结果:
在这里插入图片描述

2. 一维数组指针

int a[3]; //定义了一个3个元素的一维数组,数组名字为a,数组名代表数组首地址
int *p; // 此处 * 表示定义指针变量
p=a; //p=&a[0] // (&表示取地址运算符)表示将数组首地址赋值给p

推广:
p+i=a+i=&a[i]=&p[i] //表示数组的第i个元素的地址
*(p+i)= * (a+i)=a[i]=p[i]//表示第i个元素的地址中的值 此处 * 表示索引存储地址中的数值

例:

#include <stdio.h>

void main()
{
	int a[3],*p;
	int i;

	a[0]=2;
	a[1]=4;
	a[2]=6;

	p=a;

	printf("输出数据所在地址:\n");
	for(i=0;i<3;i++)
	printf("第 %d 个数据的存储地址:%x  %x  %x  %x\n",i,p+i,a+i,&a[i],&p[i]);

	printf("输出相应地址中的数据:\n");
	for(i=0;i<3;i++)
	printf("第 %d 个数据的存储地址中数值:%d  %d  %d  %d\n",i,*(p+i),*(a+i),*(&a[i]),*(&p[i]));
	//&a[i],&p[i]表示取数组中第i个元素的地址
	//*(地址)表示索引对应地址中的数值
}

运行结果:
在这里插入图片描述

3. 二维数组指针

float a[3][3];//对于多维数组,数组名同样代表数组首地址
int *p;
p=a[0]; //p=a;表示将数组第0行首地址赋值给p

推广:
p+i;
//二维数组的元素都按照内存顺序排列;
//表示从数组a起始地址开始第i个元素的地址,p+6表示访问第7个元素的地址//
p=a; //表示数组的起始地址
a+i= a[i] =(a+i)=&a[i]=&a[i][0]//这几个地址是等价的
a[i]+j=&a[i][j]=
(a+i)+j//表示第i行第j列的元素地址
(a[i]+j)=a[i][j]=(*(a+i)+j)//表示第i行第j列中的元素

4. 指针数组、字符串指针数组

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

int main(void)
{
	int a1[] = { 1,2,3 };	int a2[] = { 4,5,6 };	int a3[] = { 7,8,9 };
	int* num[] = { a1,a2,a3};
	for (int i = 0; i < 3; i++)
	{
		printf("%x	%x	", num + i, *(num + i));
		//	num + i 数组对应下标占用的内存地址;*(num + i) 装入的数组元素首地址
		for (int j = 0; j < 3; j++)
		{
			printf("%x  %d	", *(num + i)+j, *(*(num + i)+j));
			//	*(num + i) 数组中装有的地址;*(num + i)+j 数组中装有的地址+偏移量
			//	*(num + i) + j 解引用(数组中装有的地址 + 偏移量)元素
		}
		printf("\n");
	}
	return 0;
}

运行结果:
在这里插入图片描述
第一个红框为数组num每个下标元素占用的内存地址;第二个红框为num数组中装有数组的首地址;

#include "stdio.h"
#include "string.h"
int main(void)
{
	char str[50] = {0};
	char* substr[11] = { "AB","ABC","ABCD","ABCDE","ABCDEF","ABCDEFG","ABCDEFGH",
						 "ABCDEFGHI","ABCDEFGHIJ","ABCDEFGHIJK","ABCDEFGHIJKL" };
	//char型指针数组中,装入的数据为每个字符串的首地址
	for (int i = 0; i < 11; i++)
	{
		sprintf(str,"The string of length %02d-%0.2d is: %s.", strlen(*(substr + i)), strlen(*(substr + i)) ,*(substr +i));
		//	substr +i 数组对应下标占用的内存地址;*(substr +i) 解引用得到每个字符串的首地址(从对应下标地址中取出对应数据)
		//	sprintf   函数为 "stdio.h" 中  将格式化的数据写入字符串函数
		//	%02d、%0.2d、%.2d 功能为将数据从左边补0对齐为2位

		printf("%s\n", str);
	}
	return 0;
}

程序运行结果:
在这里插入图片描述

3. 函数指针

后面再继续补充。

扩展:

要从地址 addr,读取一个半字(半字为 16 位,字为 32 位),可以通过如下的语句读取:
data= * (vu16 *)addr;//vu16为 volatile unsigned short int
将 addr 强制转换为 vu16 指针,然后取该指针所指向的地址的值,即得到了 addr 地址的值。
类似的,将上面的 vu16 改为 vu8,即可读取指定地址的一个字节。

使用指针的2大问题:
1.未分配内存就使用
char *p;
p[1]=2;//编程时不报错,运行程序会出错
2.越界使用
char *p={1,2,3,4,5};
p[10]=12;//可能导致修改其他变量的值,还可能地址超出物理内存地址,造成编程时hardfault 报错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值