指针

JVM中的对象

柔情痞子 提交于 2020-03-01 16:31:47
划分对象 两种方式: 指针碰撞:java内存空间规整的请款下使用 空闲列表:java内存空间不规整的请款下使用 并发安全问题:频繁创建对象就会存在线程不安全问题。解决方案有两种: 1.对分配内存空间的操作进行同步处理,CAS加失败重试机制保证保证更新操作原子性。 2.分配缓冲:给每个线程分配独立空间(Java堆中申请一小块私有内存),也就是本地线程分配缓冲(Tread Local Allocation Buffer,TLAB),开启 -XX:+UseTLAB,在自己Buffer分配,空间不够重新在Eden区申请一块继续使用。 TLAB可以让每个应用线程拥有专属的分配指针来分配空间(Eden区,默认Eden的1%),减小同步开销。 TLAB只是让每个线程有私有的分配指针,但底下存对象的内存空间还是给所有线程访问的,只是其他线程无法在这个区域分配而已。当一个TLAB用满(分配指针top撞上分配极限end了),重新申请一个TLAB. 对象内存布局 在HotSpot虚拟机中,对象的内存布局分为:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding) 对象头分配两部分,一是自身运行时数据(哈希吗HashCode)、GC分带年龄、锁状态标志、线程持有锁、偏向线程ID、偏向时间戳等。 另一种类型指针,即只想它的类元素指针,虚拟机通过这个指针来确定是哪个类的实例

继承关系类之间的强制转换

寵の児 提交于 2020-03-01 16:10:55
从图中可以看出,派生类不仅有自己的方法和属性,同时它还包括从父类继承来的方法和属性。当我们从派生类向基类转换时,不管用传统的c语言还是c++转换方式都可以百分百转换成功。但是可怕是向下转换类型,也就是我们从基类向派生类转换,当我们采用传统的C语言和c++转换时,就会出现意想不到的情况,因为转换后派生类自己的方法和属性丢失了,一旦我们去调用派生类的方法和属性那就糟糕了,这就是对类继承关系和内存分配理解不清晰导致的。好在c++增加了static_cast和dynamic_cast运用于继承关系类间的强制转化。 static_cast详解: static_cast相当于传统的C语言里的强制转换,该运算符把expression转换为new_type类型,用来强迫隐式转换如non-const对象转为const对象,编译时检查,用于非多态的转换,可以转换指针及其他,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法: ①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。 进行上行转换(把派生类的指针或引用转换成基类表示)是安全的; 进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。 ②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。 ③把空指针转换成目标类型的空指针。

C语言指针用法详解(二) 指针的算术运算

…衆ロ難τιáo~ 提交于 2020-03-01 12:24:00
例题1: Question : char a[20]; int *ptr = (int * )a; ptr++ Practice : Reason : #include <bits/stdc++.h> using namespace std; int main() { char a[20]; int *ptr = (int * )a;/// 强制类型转换不会改变a的类型 /*** ** 吾日三醒指针:指针的类型,指针指向的类型,指针指向哪里 ** ptr 的类型是 int* , 指向的类型是 int , 指向整形变量 a ***/ cout<<" befor : " << ptr<<endl; ptr++; cout<< " sizeof (ptr) "<< sizeof(ptr)<<endl; /*** ** ptr 类型是指针,指针的自增,当然是增加自身的大小了 ** sizeof(ptr) 为4, ptr 增加4 ***/ cout<<" after : "<<ptr<<endl; } 例题2: Question : int arr[20] = {0}; int *ptr = arr; for (int i=0; i<20; i++) { (*ptr)++; ptr++; } Practice : Reason : #include <bits/stdc++.h> using

指针加减法运算的“定义域”

吃可爱长大的小学妹 提交于 2020-03-01 12:21:59
  指针变量加(减)一个整数。   例如:p++,p--,p+i,p-i,p+=i,p-=i等均是指针变量加(减)一个整数。   将该指针变量的原值(是一个地址)和它指向的变量所占用的存储单元的字节数相加(减)。     ————谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p290    在C语言中,任何运算都有前提条件。脱离了前提谈运算是荒谬的。   比如,一元“*”运算,其运算对象必须是非void *类型的指针。如果对一个int类型的数据或unsigned类型的数据做一元“*”运算,连编译都无法通过(这也间接说明了指针并非是一个32位无符号整数。参见§246)。   再比如,两个int类型数据相加,其前提条件是结果必须在int类型可以表示的范围之内,否则就成了一种未定义行为(undefined behavior)。   指针运算也是如此。并非所有的指针类型数据都有加(减)法运算。C语言并没有定义void *类型指针或指向函数的指针的加减法运算。换言之,指针的加减法运算只对那些指向数据对象(Object)类型的指针才可能有意义。比如:int *类型的指针可以做加减法运算。   指向数据对象类型的指针的加减法运算并没有限制运算对象是左值(lvalue)或可修改的左值(modifiable lvalue),用一句通俗的话来说

第二十九天

ⅰ亾dé卋堺 提交于 2020-03-01 09:23:21
字符数组和字符指针不是一回事 1字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第一个字符的地址),决不是将字符串放到字符指针变量中。 2赋值方法不同,对字符数组只能对各个元素赋值,不能用以下办法对字符数组赋值。 char str[20]; str=“miao”; 字符指针变量,可以采用下面方法赋值 char *; a=“miao”; 但注意赋给a的不是字符,而是字符串第一个元素的地址 3对字符指针变量赋初值 * char a=“miao”; = char *a; a=“miao”; 而对数组的初始化 char str[20]={“miao”}; 不能等价于 char str[20]; str[]=“miao”; 4如果定义了一个字符数组,在编译时为它分配内存单元,他有确定的地址,而定义一个字符指针变量时,给指针变量分配内存单元,在其中可以放一个字符变量的地址也就是说,该指针变量可以指向一个字符型数据,但如果未对它赋予一个地址值,则它并未具体指向一个确定的字符数据 5指针变量的值是可以改变的,若定义一个指针变量,并使它指向一个字符串,就可以用下标形式引用指针变量所指的字符串中的字符 用函数指针变量调用函数 可以用指针变量指向整形变量,字符串,数组,也可以指向一个函数,一个函数在编译时被分配给一个入口地址,这个函数的入口地址就称为函数的指针。

参数传递

冷暖自知 提交于 2020-03-01 08:45:27
Java参数传递,是以值的方式,而不是引用传递。 new的dog是一个指针,存储的是对象的地址。参数在传递时,本质上是将对的地址以值的形式传递。 在方法中改变对象的值,会改变原值,因为引用的是同一个对象。 如果将指针引用了其他对象,那么此时方法里和方法外的指针指向了不同对象。不会相互影响。 使用同一个对象,会改变对象的相关值。 来源: CSDN 作者: 静笃cc 链接: https://blog.csdn.net/weixin_46032375/article/details/104578307

嵌入式C语言编程小知识总结

試著忘記壹切 提交于 2020-03-01 08:38:58
嵌入式C语言编程小知识总结 1. 流水线被指令填满时才能发挥最大效能,即每时钟周期完成一条指令的执行(仅指单周期指令)。如果程序发生跳转,流水线会被清空,这将需要几个时钟才能使流水线再次填满。因此,尽量少的使用跳转指令可以提高程序执行效率,解决发案就是尽量使用指令的“条件执行”功能。 2. 在LPC2200系列中: 可以通过过下面的程序延迟10毫秒: for(i=0;i<200;i++) { for(j=0;j<200;j++); } 3. 通过下面语句将一个16位的变量放在两个8位的变量中。 //IP数据报总长度高字节 IpHeadUint8[10]=(IpHead.e_ip.Crc&0xff00)>>8; //IP数据报总长度低字节 IpHeadUint8[11]=IpHead.e_ip.Crc&0x00ff; 4. 在对全部数组元素赋初值时,可以不指定数组长度。 eg;inta[]={1,2,3,4,5}; 但如果当输出第a[5]以上的元素时,系统回输出随机数值,所以使用此方法时,不能使用超过初始值元素以上的元素。 5. 由于ADS先天性的对printf不支持;因此不便于我们调试,可以利用串口输出来代替printf来调试。 6. 用或运算,可使某位置为1,其它位不变 eg: PINSEL0 |= 0x00000005; //设置串口引脚 使第0位和第二位置一,其他位不变。 7

代码面试之广义表

社会主义新天地 提交于 2020-03-01 06:57:57
广义表的基本概念 广义表(Lists,又称列表) 是线性表的推广。线性表定义为n>=0个元素a1,a2,a3,…,an的有限序列。线性表的元素仅限于原子项,原子是作为结构上不可分割的成分,它可以是一个数或一个结构,若放松对表元素的这种限制,容许它们具有其自身结构,这样就产生了广义表的概念。 广义表是n (n>=0)个元素a1,a2,a3,…,an的有限序列,其中ai或者是原子项,或者是一个广义表。通常记作LS=(a1,a2,a3,…,an)。LS是广义表的名字,n为它的长度。若ai是广义表,则称它为LS的子表。 抽象数据类型广义表的定义如下: ADT Glist { 数据对象: D={ei | i=1,2,..,n;n>=0 ; eiÎAtomSet 或ei ÎGlist, AtomSet为某个数据对象} 数据关系:R1={< ei-1, ei > | ei-1 , ei ÎD,2<=i<=n} 基本操作: InitGList( &L); 操作结果:创建空的广义表L。 CreateGList(&L,S); 初始条件:S是广义表的书写形式串。 操作结果:由S创建广义表L。 DestroyGList(&L); 初始条件:广义表L存在。 操作结果:销毁广义表L。 CopyGList( &T,L); 初始条件:广义表L存在。 操作结果:由广义表L复制得到广义表T。 GListLength

java如何获取一个对象的大小

烂漫一生 提交于 2020-03-01 04:36:43
When---什么时候需要知道对象的内存大小 在内存足够用的情况下我们是不需要考虑java中一个对象所占内存大小的。但当一个系统的内存有限,或者某块程序代码允许使用的内存大小有限制,又或者设计一个缓存机制,当存储对象内存超过固定值之后写入磁盘做持久化等等,总之我们希望像写C一样,java也能有方法实现获取对象占用内存的大小。 How---java怎样获取对象所占内存大小 在回答这个问题之前,我们需要先了解java的基础数据类型所占内存大小。 数据类型 所占空间(byte) byte     1 short 2 int 4 long 8 float 4 double 8 char   2 boolean 1 当然,java作为一种面向对象的语言,更多的情况需要考虑对象的内存布局,java对于对象所占内存大小需要分两种情况考虑: 对象类型 内存布局构成 一般非数组对象 8个字节对象头(mark) + 4/8字节对象指针 + 数据区 + padding内存对齐(按照8的倍数对齐) 数组对象 8个字节对象头(mark) + 4/8字节对象指针 + 4字节数组长度 + 数据区 + padding内存对齐(按照8的倍数对齐) 可以看到数组类型对象和普通对象的区别仅在于4字节数组长度的存储区间。而对象指针究竟是4字节还是8字节要看是否开启指针压缩。Oracle JDK从6 update

关键字(nonatomic/atomic)、(copy/retain/assign/strong/weak )、(readonly / readwrite)、(@property/@

落花浮王杯 提交于 2020-03-01 04:00:01
property关键字:设置成员变量的属性(有读/写,赋值assign,retain,copy ,以及对多线程的支持nonatomic) (1)nonatomic/atomic atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。 atomic :原子性访问,设置成员变量的@property属性时,默认为atomic,提供多线程安全。 在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。加了atomic,setter函数会变成下面这样: {lock} if (property != newValue) { [property release]; property = [newValue retain]; } {unlock} nonatomic :非原子性访问,对属性赋值的时候不加锁,多线程并发访问会提高性能。如果不加此属性,则默认是两个访问方法都为原子型事务访问。 atomic是Objc使用的一种线程保护技术,在多线程环境下,解析的访问器提供一个对属性的安全访问,从获取器得到的返回值或者通过设置器设置的值可以一次完成,即便是别的线程也正在对其进行访问。如果你不指定 nonatomic ,在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果指定了 nonatomic ,那么访问器只是简单地返回这个值。基本上来讲