关于C指针

C 语言中指针可以说是其精华,常有一句话,学会了指针你也就学会了 C 语言。但是很多人不能理解指针。我写这篇文章的目的是帮助大家理解指针,内容都是跟人的见解,没有指针基础的、C语言高手和不喜欢的就别看了。

下面摘自百度百科:

大家都认为,c语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上。因此,说指针是c语言的灵魂,一点都不为过。同时,这种说法也让很多人产生误解,似乎只有C语言的指针才能算指针。basic不支持指针,在此不论。其实,pascal语言本身也是支持指针的。从最初的pascal发展至今的objectpascal,可以说在指针运用上,丝毫不会逊色于c语言的指针。

首先我们来看看NULL的定义:

#ifdef __cplusplus

#define NULL    0

#else

#define NULL    ((void *)0)

#endif

NULLC++中的定义就是0,在C中的定义是(void *0,本质上还是0;指针的值说白了就是一个数字,这个数字存在一个变量中,这个变量就称为指针。

那么说随便一个数字都行吗?肯定不是。这个数字是用来表示内存单元的,因此它必须是合法的内存地址,不管在什么系统上它的值在ULONG(unsigned long)范围内,ULONG32位系统上是0-0xFFFFFFFF,在64位系统上就是0-0xFFFFFFFFFFFFFFFF;也就是说ULONG根据运行环境改变。

32位操作系统为例,在操作系统加载的时候要接管内存,那么它怎么管理呢?就是给每个内存单元编号,这个编号是一个ULONG类型的整数,所以它只能从0编号到0xFFFFFFFF,在普通PC上最小寻址单元是Byte(字节),也就是最多可以编号0x100000000个字节=4GB,这也就是为什么大于4G内存的电脑都需要安装64位操作系统的原因,32位操作系统最高支持4G内存,超出部分无法编号,操作系统也就不能管理,因此不能被使用。

        

注:以下以为32位系统

         C语言中指针就是一个编号,不管什么类型的指针都是以个ULONG类型的整数。那么你不禁要问,为什么我们在定义指针的时候还要指定类型?

举个例子:

void IncreaseInt(int *pi)
{
	(*pi) += 256;
}
void IncreaseChar(char *pc)
{
	(*pc)++;
}
int main()
{
	int a = 0;
	char b = 'A';
	IncreaseInt(&a);
	printf("%d\n", a);
	IncreaseChar(&b);
	printf("%c\n", b);
	getchar();
	return 0;
}

         在函数IncreasInt中我们使用了“*”运算符,*运算符就是我们从内存的位置取出值。假设变量a的地址是0x1000,传到函数IncreasIntpi的值就是0x1000,我们使用“*”就可以从内存的0x1000处取往后4个字节,加上256后放进0x1000-0x1003在函数IncreasChar中我们也使用了“*”运算符,假设b的地址是0xffc,传到函数IncreasCharpc的值就是0xffc,我们使用“*”就可以从内存的0xffc处取1个字节,自增之后放进0xffc里。

         那么编译器怎么知道“*”要取几个字节,这就是指针类型的作用了,指针类型就是告诉编译器这个指针指向的目标占用的内存是多大,使用*[]的时候才知道要取几个字节。

————————————————————————————割了————————————————————————————

    最近项目太忙,把这个给忘了,七夕闲着没事,给补上。

    不管数据在硬盘还是内存中,数据的都是以二进制的方式存在的,比如有一块存储空间的数据是:00010100000100000000000000000000,在工具中为了方便一般使用16进制:41 01 00 00;X86的计算机都是按照小端存储的(什么是小端存储自行百度),这个数据如果使用int类型就是0x141即321,如果使用char是0x41,只取出来第一个字节,不管什么类型来表示数据都是不变的,其实本质上他们是同一块数据。指针表示的就是某块内存的地址。也就是说如果上述存储空间是内存,地址是0x1000,那么如果是int* p = 0x1000,那么*p的值就是0x141,如果是char*  p = 0x1000, *p的值就是0x41。
    从上面的讲述中大家应该可以明白,内存中存储数据跟类型无关,它不考虑你是什么类型,只有程序才去考虑类型;因为同样一块数据使用不同类型取出的值一样,比如0xffffffff,使用unsigned int 取值是4294967295,使用int取值是-1,使用unsigned char 取值是255(0xff),下面有个例子:

 int main()
 {
	 int a = 0;
	 int b[2];
	 b[2] = 10;
	 printf("%d\n", a);
	 return 0;
 }

 
    请问输出的值是多少?
    
应该有相当一部分人认为会输出0, 认为是10并且知道原因的请绕道,本文不适合你。不知道结果的继续往下看,我先不说答案:
简单划一下函数的栈内存示意图:
假设main函数基址为bp  

                    参数空间(本例无参)
main函数基址 ----------------------------------------------- bp 
                    a的地址即&a为bp-4
                    b[1]的地址bp-8
                    b[0]的地址bp-12

    假设int* p = b;那么&b[0] = p, &b[1] = p + 1,以此类推b[2] = p + 2 ,那么字节偏移就是:p = &b[0] = bp - 12,那么p + 2就是bp - 4,即a;惊奇的发现b[2]就是a,所以本例输出的结果是10。能把这题看透彻,指针应该学的不会太差。



    就写这些了,不写不知道,一写发现真难,举例子很难举。 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值