指针

container_of宏深度解析

走远了吗. 提交于 2020-02-04 01:24:00
作用: 由结构体中某个元素的指针,推出整个结构体变量的指针。 原型: #define container_of(ptr,type,member) {const typeof(((type*)0)->member)* _myptr=(ptr); (type*)((char*)_myptr-offsetof(type,member));}) 变量分析: ptr指向结构体元素member元素的指针;type为结构体类型;member为结构体中的某个元素;typeof为C语言的关键字,用来由变量得到变量的类型,eg;typeof(a)得到变量a的类型。 typeof(((type*)0)->member)* _myptr=(ptr)类似于(int)* p=(ptr)。 宏解析: 先用typeof得到member元素的类型,定义为一个指针( _myptr);然后用这个指针减去该元素相对于结构体首地址的偏移量,就得到整个结构体变量的首地址了,再把这个地址强制类型转换为type*即可(得到指针)。 举例: # include <stdio.h> struct mystruct { char a ; int b ; short c } ; # define container_of(ptr,type,member) { const typeof ( ( ( type * ) 0 ) ->

左神算法笔记(六)——链表

陌路散爱 提交于 2020-02-04 01:16:34
回文链表 创建一个栈,将链表中所有数据存入栈中,再将栈中数据与链表中的所有数据进行比较。 利用单步指针和双步指针,当双步指针最后到链表尾的时候,将后半部分链表指向取反,再从链表头和链表尾同时开始对比数据大小,实现回文链表的判断。空间复杂度为O(1)。 public static class Node { public int value ; public Node next ; public Node ( int data ) { this . value = data ; } } //需要n个额外空间 public static boolean isPalinddrome1 ( Node head ) { Stack < Node > stack = new Stack < Node > ( ) ; //建立一个node类型的栈 Node cur = head ; while ( cur != null ) { stack . push ( cur ) ; cur = cur . next ; } while ( head != null ) { if ( head . value != stack . pop ( ) . value ) { return false } head = head . next ; } return true ; } //需要n/2个额外空间

C++对象模型

余生颓废 提交于 2020-02-04 01:03:41
C++在布局以及存取时间上的额外负担是由以下因素导致的 vitual function 机制,用来支持一个有效率的执行期绑定 vitrual base class,用以实现“多次出现在继承体系中的base class”,有一个单一而被共享的实例 多重继承的额外负担,发生在一个派生类和其第二或后继的基类之间的转换 C++是如何支持虚函数的 每个class产生指向每一个虚函数的指针,放在表格中,这个表格就是虚表 每个类对象被插入了一个指针,指向虚表,这个指针就是虚表指针, 虚表指针的设定和重置都由每一个class的构造、析构和赋值运算符自动完成 ,每一个类所关联的type_info object(用来支持runtime type identification)也是经过虚表指出的,通常放在虚表中的第一个位置 一个对象有多大 其非静态成员的总和大小 任何犹豫对其的需求而填补上的空间(可能存在于成员之间,也可能存在于集合边界) 加上为了支持虚机制而产生的任何额外负担 什么时候编译器会产生默认构造函数 对于class X,如果没有任何的用户定义构造函数,那么会有一个默认构造函数被隐式声明出来,这个默认的构造函数将是一个trivial(没有什么用的)的构造函数 默认构造函数在 被需要 的时候被编译器产生出来,这里的被需要分为两种情况,一种是程序的需要,这种需要应该由程序员来满足

算法笔记--野指针问题

烂漫一生 提交于 2020-02-04 00:32:41
野指针:一个指针在free之后没有被赋值成NULL。 造成野指针的原因:在函数free(p)中只是将P指针的值传递给了函数,仅仅是释放了形参的值,实参的值并没有改变, 并且malloc函数在操作系统分配的时候是顺序分配(比如释放了的p原本使用的地址为2000, 那么下一次malloc分配的地址就是这个2000),如果继续对p进行解引用的话, 会连同下一次动态分配的指针所指向的值一同改变。 举个栗子: # include <stdio.h> # include <stdlib.h> int main ( void ) { int * p , * p1 , * p2 ; p = ( int * ) malloc ( 4 ) ; * p = 1 ; printf ( "p分配到的地址是:%X\n" , p ) ; p1 = ( int * ) malloc ( 4 ) ; * p1 = 2 ; free ( p ) ; printf ( "p释放之后p中存储的地址是:%X\n" , p ) ; p2 = ( int * ) malloc ( 4 ) ; printf ( "p2分配到的地址是:%X\n" , p2 ) ; * p = 3 ; printf ( "*p=%d *p2=%d" , * p , * p2 ) ; return 0 ; } /* 输出结果: -----------

Runtime之IMP指针,isa指针

余生颓废 提交于 2020-02-04 00:27:32
要了解 isa 指针先了解下类的定义 在xcode中用快捷键Shift+Cmd+O 搜索objc.h 能看到类的定义: 了解 Paste_Image.png 可以看出: objc_object:Objective-C对对象的定义, 其质上是结构体对象,其中 isa是它唯一的私有成员变量,即所有对象都有isa指针 Class 是一个 objc_class 结构类型的指针 id是一个 objc_object 结构类型的指针,这也是id可以指向任何对象的原因 SEL(方法选择器)是一个objc_selector结构类型的指针 IMP 先不提 再搜runtime.h Paste_Image.png 每个对象结构体的首个成员是Class类的变量,该变量定义了对象所属的类,通常称为isa指针 super_class:父类,如果该类已经是最顶层的根类,那么它为NULL。 version:类的版本信息,默认为0 info:供运行期使用的一些位标识。 instance_size:该类的实例变量大小 ivars:成员变量的数组 struct objc_method_list **methodLists OBJC2_UNAVAILABLE : 方法列表,类目就是通过它添加方法的 struct objc_cache *cache OBJC2_UNAVAILABLE : 方法缓存

8.Go语言基础之指针

元气小坏坏 提交于 2020-02-04 00:27:09
Go语言中的指针不能进行偏移和运算,是安全指针。 在了解GO语言中的指针前,首先需要知道三个概念:指针地址、指针类型和指针取值。 1.Go语言中的指针 任何数据载入内存后,在内存中都有对应的地址,这就是指针。 为了保存一个数据在内存中的地址,需要指针变量。 比如"好好学习,天天向上"这个字符串写入程序中,程序一启动这句话就加载到内存(假设内存地址为0x123456),在程序中,把该字符串赋值给变量A,把该字符串的内存地址赋值给变量B。 这时变量B就是一个指针变量。通过变量A和变量B都能找到该字符串。 Go语言中的指针不能进行偏移和运算,因此Go语言中的指针操作非常简单,只需要记住两个符号:&(取地址)和*(根据地址取值)。 也需要记得: 值类型有:int、float、bool、string、array、struct 引用类型有:指针,map,切片,chan 1.1指针地址和指针类型 每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。 Go语言中使用&字符放在变量前面对变量进行“取地址”操作。 Go语言中的值类型(int,float,bool,string,array,struct)都有对应的指针类型,如*int,*in64,*string等。 取变量指针的语法如下: ptr := &v // v的类型为T 其中: v:代表被取地址的变量,类型为T ptr

iOS 认识runtime 中的三个指针 isa , IMP , SEL

左心房为你撑大大i 提交于 2020-02-04 00:26:11
runtime中函数调用经常被提及的三个概念 isa,IMP,SEL 一 isa: 是类指针,之所以说 isa 是指针是因为 Class 其实是一个指向 objc_class 结构体的指针,而isa 是它唯一的私有成员变量,即所有对象都有isa指针(isa位置在成员变量第一个位置) //打开 runtime.h文件可看到下面的类的结构体详情内容struct objc_class { Class _Nonnull isa OBJC_ISA_AVAILABILITY;//这个就是上面说的 每个对象都有isa指针 在结构体指针中第一个成员变量的位置上 #if !__OBJC2__ Class _Nullable super_class /*父类*/ const char * _Nonnull name /*类名*/ long version /*版本信息*/ long info /*类信息*/ long instance_size /*实例大小*/ struct objc_ivar_list * _Nullable ivars /*实例参数链表*/ struct objc_method_list * _Nullable * _Nullable methodLists /*方法链表*/ struct objc_cache * _Nonnull cache          /*方法缓存*/

iOS 编码复习(二)—— runtime

半世苍凉 提交于 2020-02-04 00:15:33
最近特意看了很多篇关于runtime的文章。所以自己也想把了解的东西总结一下,以便以后大家一起学习。首先必须要诚实地说一句,这里都是看了别人的文章后,用自己的话总结出来的,而没有像其他额大牛样去用c语言去写一个swizzle method之类的。 首先要说,OC是一门运行时语言,因为它不像c++在编译的时候就会检查所有函数调用,而是运行时才会检查。 先来看看[target dosomething:varl];编译器会把它编译成什么:objc_msgsend(target,@selector(dosomething:),varl);你会发现这是一个c方法。那什么是runtime呢?runtime其实就是一个运势时的c语言写成的基础库,oc的程序必须得到runtime的的运行才能正常work。 下面我们来介绍一下对象和类。它们其实就是用c语言封装的结构体。(感受下面向对象与面向过程语言的区别) oc里的class实际上就是一个 objc_class 结构体的指针: typedef struct objc_class *Class; struct objc_class { Class isa OBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class super_class OBJC2_UNAVAILABLE; // 父类 const char *name

《c++primer》笔记 第3章 字符串、向量和数组

廉价感情. 提交于 2020-02-03 09:52:04
标准库类型 本章重要的两个: string 和 vector ,以及配套的迭代器。 3.1 命名空间的using声明 using声明具有如下的形式: using namespace::name; 一旦声明了上述语句,就可以直接访问命名空间中的名字: #include<iostream> //using声明,当我们使用名字cin时,从命名空间std中获取它 using std::cin; int main() { int i; cin >> i;//正确:cin和std::cin含义相同 cout << i;//错误:没有对应的using声明,必须使用完整的名字 std::cout << i;//正确:显式地从std中使用cout return 0; } 用下面的using可以使用std里面的所有名字: using namespace std; 头文件不应包含using声明 3.2 标准库类型string 初始化string对象的方式 string s1; //默认初始化,si是一个空串 string s2(s1); //s2是s1的副本 string s2=s1; //等价于s2(sl>,s2是s1的副本 string s3("value"); //S3是字面值"value"的副本,除了字面值最后的那个空字符外 string s3="value"; //等价于s3("value")

C++引用与指针(一):引用

北城余情 提交于 2020-02-03 03:52:30
1. 引用基本概念及说明 引用 就是为已有的对象a所起的另外一个名字b,可以通过引用去修改b以实现对象a的修改。 引用格式: 类型说明符 &引用名=变量名 例程: int i; int &ri=i; i=5; cout<<i<<endl; ri=10; cout<<ri<<endl; &不是C语言中的取地址运算,而是标识符 类型说明符必须和目标变量类型一致 说明 : 引用在声明时必须初始化 一个实体可以有多个引用,但是一个引用只能引用一个实体 引用即别名,相当于目标对象有一个原名和别名,引用不是对象,所以也无法作为另外一个引用的原名。 不能建立数组的引用 2. 引用的实际应用 2.1 引用作为参数 还记得在C语言中,如果要对函数传入可以在函数内部修改,且修改有效的变量时,我们需要使用传入指针。而C++中,引用提供了传入可修改变量的一种方法,见例子 //p1,p2均为引用 void swap(int& p1, int& p2) { int p; p = p1; p1 = p2; p2 = p; } int main() { int a = 1, b = 2; cout << "交换前,a和b" << " " << a << " and " << b << endl; swap(a, b); cout << "交换后,a和b" << " " << a << " and " << b <