指针学习混淆点

本文详细介绍了C语言中的指针概念,包括指针的大小(由计算机的寻址能力决定),指针常量与常量指针的区别,以及指针的各种操作如算术运算、数组、二级指针、函数指针和万能指针void*的应用。此外,还提到了动态内存管理函数如malloc、calloc、realloc和memset的使用。
摘要由CSDN通过智能技术生成

指针的大小说明

指针存放的内容是什么?其大小取决什么?

指针在内存中存储的是一个内存地址,因为指针要能够指向内存地址里面的每个地址,而内存地址的长度取决于底层计算机的寻址能力(MAR的位数,存储单元的个数)。

不同位数计算机指针大小

在32位系统中,底层计算机的寻址空间为2的32次方,为了能访问到其中的每个地址,所以指针占用4个字节(32位)(因为一个字节等于八位);同理,在64位系统中占用8个字节(64位)。

指针常量和常量指针

先说结论:
指针常量是指一个指针,它指向的内存地址是固定的,不可更改。也就是说,指针常量指向的值是常量,不能通过该指针修改该值。但是指针本身的值(指向的地址)可以改变。
常量指针,指向常量的指针。该指针指向一个常量,常量的值不可变,不可以通过该指针修改其值,但是该指针可以指向其他常量。

常量指针

const int value = 100;
const int * pValue = &value;
*pValue = 200;// error 这个是错误的 不能修改一个常量的值 因为该指针指向一个常数
pValue = 200;// 该条语句是成功的

指针常量

int value = 100;
int*const pValue = &value;
pValue = 0x00; // 不被允许,因为是个常量指针
*pValue =200;// OK

指针变量的算数操作

示例代码:

int * pNumber = NULL;
pNumber = 0x0;

++pNumber;//0x4
pNumber + 2; //0x0c
  1. 指针变量的算数运算地址增加的长度和数据类型有关,示例中指针指向一个int类型,一个int型数据占4个字节,现在计算机一般都是以字节为单位进行编码的,即代表一个地址单位代表一个字节,则++pNumber之后,pNumber指向的地址会向后移动四个字节。pNumber+2继续向后移动八个字节。
  2. 若是char类型,++操作只会移动一个字节,以此类推double类型会移动8个字节。
  3. 这里不要和指针的大小弄混,指针变量也是个变量,存储的是地址。算数操作是对存储的地址值进行操作

指针和数组

数组是存储若干相同数据类型元素且地址连续的集合,数组也是有地址的,数组名就是该数组的首地址,数据名可以看做是一个特殊的常量指针,我们可以通过指针的偏移(++,–)对数组进行访问,示例如下:

int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int *pArr = arr; // 这里不需要使用&数组名就是首地址
pArr[5] = 10;	// 第一种访问方式
*(pArr+5) = 20;	// 第二种访问方式

二级指针(指向指针的指针)

	int a = 10;
	// 一级指针是一个*
	int* p = &a;// 指针p保存了a的地址
	// 二级指针是二个*
	int** pp = &p;// 指针pp 保存了p的地址
	// 利用pp和p访问a
	// *值取指针保存地址的值
	printf("pp = %d,p = %d", **pp, *p);

一级指针:
指针变量p的类型为int* ,所指向的类型为int, 指针变量p指向了int类型a的内存地址
二级指针:
指针变量pp的类型为int**, 所指向的类型为int*, 指针变量p的类型为int*,所以pp指向p的内存地址,即pp保存的是p的首地址,*pp访问到的是p所储存的值,**p访问到的是a的值。

指针数组(保存指针的数组)

顾名思义,数组里面的每个元素都是一个指针类型的变量

// 声明指针数组
// 数据类型* 变量名[长度];
int* p1[10];
int a1 = 0, a2 = 0, a3 = 0;
p1[0] = &a1;
p1[1] = &a2;
p1[2] = &a3;
*(p1[0]) = 10;
*(p1[1]) = 20;
*(p1[2]) = 30;
printf("%d %d %d\n", a1, a2, a3);

数组指针(指向数组的指针)

我也没弄懂这个东西要干嘛,感觉没有什么实际的作用

// 数组指针
// 数据类型 (*变量名)[数组长度];
// 该数组指针指向一维数组
int(*p)[10];
int a[10];
// 数组指针的赋值
// 变量名 = 数组的地址
p = a;
// 数组指针的使用
//(*变量名)[数组长度] = 值
(*p)[0] = 10;

函数指针(指向函数的指针)

// 函数指针的声明
// 数据类型 (*变量名)(参数列表);
// 函数名 就是函数的首地址,函数名的作用,只是给人类识别用的(在汇报层面绘转换为二进制[地址])
void Print1()
{
	printf("Hello World\n");
}

void Print2()
{
	printf("Hello World2\n");
}

int main()
{
	void (*p)();
	// 只要函数的参数和返回值相同就可以直接调用和赋值
	p = Print1;
	p();

	p = Print2;
	p();

}

万能指针void *

void *指针可以指向任意变量的内存空间:

	void *p = NULL;

	int a = 10;
	p = (void *)&a; //指向变量时,最好转换为void *

	//使用指针变量指向的内存时,转换为int *
	*( (int *)p ) = 11;
	printf("a = %d\n", a);

以下是一些C语言中返回类型为void*的常见函数:

  1. malloc:动态分配内存,并返回指向分配内存块的指针。
void* malloc(size_t size);
  1. calloc:动态分配内存,并初始化为零,并返回指向分配内存块的指针。
void* calloc(size_t num, size_t size);

  1. realloc:重新分配先前分配的内存块的大小,并返回指向重新分配后内存块的指针。
void* realloc(void* ptr, size_t size);

  1. memset:将一块内存区域的内容设置为指定的值,并返回指向该内存区域的指针。
void* memset(void* ptr, int value, size_t num);

Stkcd [股票代码] ShortName [股票简称] Accper [统计截止日期] Typrep [报表类型编码] Indcd [行业代码] Indnme [行业名称] Source [公告来源] F060101B [净利润现金净含量] F060101C [净利润现金净含量TTM] F060201B [营业收入现金含量] F060201C [营业收入现金含量TTM] F060301B [营业收入现金净含量] F060301C [营业收入现金净含量TTM] F060401B [营业利润现金净含量] F060401C [营业利润现金净含量TTM] F060901B [筹资活动债权人现金净流量] F060901C [筹资活动债权人现金净流量TTM] F061001B [筹资活动股东现金净流量] F061001C [筹资活动股东现金净流量TTM] F061201B [折旧摊销] F061201C [折旧摊销TTM] F061301B [公司现金流1] F061302B [公司现金流2] F061301C [公司现金流TTM1] F061302C [公司现金流TTM2] F061401B [股权现金流1] F061402B [股权现金流2] F061401C [股权现金流TTM1] F061402C [股权现金流TTM2] F061501B [公司自由现金流(原有)] F061601B [股权自由现金流(原有)] F061701B [全部现金回收率] F061801B [营运指数] F061901B [资本支出与折旧摊销比] F062001B [现金适合比率] F062101B [现金再投资比率] F062201B [现金满足投资比率] F062301B [股权自由现金流] F062401B [企业自由现金流] Indcd1 [行业代码1] Indnme1 [行业名称1] 季度数据,所有沪深北上市公司的 分别包含excel、dta数据文件格式及其说明,便于不同软件工具对数据的分析应用 数据来源:基于上市公司年报及公告数据整理,或相关证券交易所、各部委、省、市数据 数据范围:基于沪深北证上市公司 A股(主板、中小企业板、创业板、科创板等)数据整理计算
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值