BeginMan blog

C语言的sizeof关键字

此篇为《C语言点滴》关于sizeof的总结

sizeof 是C 语言的一个关键字不是一个函数。但是它的行为类似于一个函数,因为它返回一个类型为size_t 的无符号的整型数。我们通常用sizeof来计算变量所占内存的真实尺寸。

sizeof(指针)和sizeof(数组)的区别

#include <stdio.h>

int main()
{
	int a[] = {0, 1, 2, 3, 4, 5};
	char c[] = {'a', 'b'};
	int* ip = a;
	char* cp = c;
	printf("sizeof(ip)=%lu\n", sizeof(ip));
	printf("sizeof(cp)=%lu\n", sizeof(cp));
	printf("sizeof(a)=%lu\n", sizeof(a));
	printf("sizeof(c)=%lu\n", sizeof(c));
	// “根据数组名a 来计算数组到底有多少个元素”
	printf("sizeof(a/a[0])=%lu\n", sizeof(a) / sizeof(a[0]));
}

打印出来的结果:

sizeof(ip)=8
sizeof(cp)=8
sizeof(a)=24
sizeof(c)=2
sizeof(a/a[0])=6

对指针利用sizeof 得到的都是一个相同的值。在C语言中,指针只保存一个地址,所以任何类型的指针都占用相同的字节数(指针大小 4 or 8)。对数组名利用sizeof 得到的是整个数组占用的字节数。

10分钟了解DNS

今天万网DNS解析出问题了,貌似被攻击了,导致华北地区部分域名解析出现问题,当时APP网络请求异常缓慢,抓包一看,原来是DNS解析耗时了5s,最后还挂了,我还以为是我处理的DNS出现了问题,瞎折腾了一会发现并不奏效,一提工单,md,原来是阿里云它们自己的问题,可见对自己多没自信。那趁这个机会复习下DNS。

一.hosts

由于IP地址不便记忆,所以产生了域名(一种主机识别码的东西,为每台主机赋予唯一主机名),为此需要有hostName -> IP 的机制,主机利用一个hosts的数据库文件来实现。

hosts文件是一个用于储存计算机网络中各节点信息的计算机文件。这个文件负责将主机名称映射到相应的IP地址。hosts文件通常用于补充或替换网络中DNS的功能。和DNS不同的是,计算机的用户可以直接对hosts文件进行控制。

hosts文件作用:

  1. 主机名到IP地址的映射
  2. 重定向, 如将server_a 重定向到其他IP。
  3. 减少对DNS服务器的访问来加快访问速度并减少带宽消耗。

对于重定向,有很好的作用,如:

将黄易163.com 重定向到一个其他IP地址,比如重定向到一个白易网站, 可以这样做:

# sudo vim /etc/hosts
123.53.214.30 163.com

如果想屏蔽一个网站,如百度,可以这样做, 该网站的域名映射到错误的IP或自己计算机的IP:

127.0.0.1 屏蔽的网站
0.0.0.0 屏蔽的网站

如下是屏蔽前后的效果:

$ curl baidu.com
<html>
<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
</html>

# 屏蔽后
$ curl baidu.com                        
curl: (7) Failed to connect to baidu.com port 80: Connection refused

如果你想加速一个网站的访问,跳过DNS解析的部分,因为有些国外的网站DNS解析太慢,更改hosts文件可减少解析,直接访问。比如加速github的访问:

185.31.17.185 github.global.ssl.fastly.net

还比如最新可用的google hosts文件

如果对一些数据库服务器,访问时输入IP地址不能访问的,只能输入服务器名才能访问。那么我们配置好Hosts文件,这样输入服务器名就能顺利连接了。

二.DNS

2.1 dns

光hosts肯定不行,它只是个本地补充而已,需要一个大的系统来管理主机名和IP地址映射关系,这就是DNS. 如下解析流程:

域名分类如下:

每一层都有域名服务器,如通过域名查找一个网站过程

DNS如同互联网中的分布式数据库,主机名->IP只是其中的一部分,主机名->IP 的对应信息叫A记录,IP->主机名 的信息叫PTR, 上层或下层域名服务器IP地址的映射信息叫NS记录; 邮件地址与邮件服务器主机名的映射信息叫MX记录.

2.2 域名解析

2.2.1 A记录

IP指向,对于泛域名解析即将该域名所有未指定的子域名都指向一个空间。在“主机名”中填入*,类型为A.

2.2.2 CNAME

别名指向, 为一个主机设置别名, 比如用github page 来写博客,那么在CNAME文件中写你的域名,如beginman.cn, 然后取解析。那么就问 github.beginman.io 设定了一个叫 beginman.cn的别名,也就是绑定了自己的域名。注意,CNAME的目标主机地址只能使用主机名,不能使用IP地址;主机名前不能有任何其他前缀,如:http://等是不被允许的;A记录优先于CNAME记录。即如果一个主机地址同时存在A记录和CNAME记录,则CNAME记录不生效。

2.2.3 NS记录

解析服务器记录。用来表明由哪台服务器对该域名进行解析。这里的NS记录只对子域名生效。

如用户希望由IP为xx.xx.xx.xxx或域名为ns.mydomain.com这台服务器来解析xx.mydomain.com,则需要设置xx.mydomain.com的NS记录。NS记录优先于A记录。

三.Linux DNS处理

Linux有两个相关命令,nslookupdig, ns也就是name servers缩写, 对域名解析检查方法:

$ nslookup -q=a www.youdomain.com

如果返回的记录只有一个IP且是当前使用的主机IP,则解析正常。如果返回的记录有多个IP地址,则解析有问题,需要修改解析。

如解析zhihu域名

$ nslookup www.zhihu.com
Server:		223.5.5.5          # DNS服务器的主机名
Address:	223.5.5.5#53           # DNS服务器IP地址

Non-authoritative answer:       # 非权威服务器的应答
www.zhihu.com	canonical name = eclipse.zhihu.com.   # cname = eclipse.zhihu.com. 别名

Name:	eclipse.zhihu.com         # 解析的URL
Address: 115.159.241.25         # 解析出来的IP

Name:	eclipse.zhihu.com
Address: 115.159.241.95

要了解上面的这些输出,就要搞清楚DNS的整个解析过程, 参考DNS解析过程详解:

  1. 现在我有一台计算机,通过ISP接入了互联网,那么ISP就会给我分配一个DNS服务器这个DNS服务器不是权威服务器,而是相当于一个代理的dns解析服务器,他会帮你迭代权威服务器返回的应答,然后把最终查到IP返回给你。
  2. 现在的我计算机要向这台ISPDNS发起请求查询www.zhihu.com这个域名了,(这里准确来说不是ISPDNS,而应该是用户自己电脑网络设置里的DNS,并不一定是ISPDNS。比如也有可能你手工设置了8.8.8.8)
  3. ISPDNS拿到请求后,先检查一下自己的缓存中有没有这个地址,有的话就直接返回。这个时候拿到的ip地址,会被标记为非权威服务器的应答
  4. 如果缓存中没有的话,ISPDNS会从配置文件里面读取13个根域名服务器的地址(这些地址是不变的,直接在BIND的配置文件中)
  5. 然后像其中一台发起请求。
  6. 根服务器拿到这个请求后,知道他是com.这个顶级域名下的,所以就会返回com域中的NS记录,一般来说是13台主机名和IP。
  7. 然后ISPDNS向其中一台再次发起请求,com域的服务器发现你这请求是zhihu.com这个域的,我一查发现了这个域的NS,那我就返回给你,你再去查
  8. .ISPDNS不厌其烦的再次向zhihu.com这个域的权威服务器发起请求,zhihu.com收到之后,查了下有www的这台主机,就把这个IP返回给你了
  9. 然后ISPDNS拿到了之后,将其返回给了客户端,并且把这个保存在高速缓存中。

第一步ISP接入互联网分配的DNS服务器是动态的,在/etc/resolv.conf文件里,具体可参考DNS域名解析的配置文件/etc/resolv.conf

$ cat /etc/resolv.conf
#
# Mac OS X Notice
#
# This file is not used by the host name and address resolution
# or the DNS query routing mechanisms used by most processes on
# this Mac OS X system.
#
# This file is automatically generated.
#
nameserver 223.5.5.5
nameserver 119.29.29.29
nameserver 8.8.8.8
nameserver 114.114.114.114

dig工具来跟踪一下:


$ dig +trace www.zhihu.com

# 第一步是向我这台机器的ISPDNS获取到根(`.`)域服务区的13个IP和主机名[b-j].root-servers.NET.
; <<>> DiG 9.8.3-P1 <<>> +trace www.zhihu.com
;; global options: +cmd
.			143034	IN	NS	m.root-servers.net.
.			143034	IN	NS	a.root-servers.net.
.			143034	IN	NS	g.root-servers.net.
.			143034	IN	NS	d.root-servers.net.
.			143034	IN	NS	c.root-servers.net.
.			143034	IN	NS	k.root-servers.net.
.			143034	IN	NS	h.root-servers.net.
.			143034	IN	NS	j.root-servers.net.
.			143034	IN	NS	i.root-servers.net.
.			143034	IN	NS	f.root-servers.net.
.			143034	IN	NS	e.root-servers.net.
.			143034	IN	NS	l.root-servers.net.
.			143034	IN	NS	b.root-servers.net.
;; Received 525 bytes from 223.5.5.5#53(223.5.5.5) in 196 ms

# 第二步是向其中的一台根域服务器(Servername就是末行小括号里面的)发送www.zhihu.com的查询请求,返回了`com.`顶级域的服务器IP(未显示)和名称

com.			172800	IN	NS	d.gtld-servers.net.
com.			172800	IN	NS	k.gtld-servers.net.
com.			172800	IN	NS	g.gtld-servers.net.
com.			172800	IN	NS	c.gtld-servers.net.
com.			172800	IN	NS	e.gtld-servers.net.
com.			172800	IN	NS	m.gtld-servers.net.
com.			172800	IN	NS	h.gtld-servers.net.
com.			172800	IN	NS	i.gtld-servers.net.
com.			172800	IN	NS	a.gtld-servers.net.
com.			172800	IN	NS	b.gtld-servers.net.
com.			172800	IN	NS	f.gtld-servers.net.
com.			172800	IN	NS	l.gtld-servers.net.
com.			172800	IN	NS	j.gtld-servers.net.
;; Received 491 bytes from 192.203.230.10#53(192.203.230.10) in 672 ms

# 第三步,便向`com.`域的一台服务器192.203.230.10请求,www.zhihu.com,他返回了`zhihu.com`域的服务器IP(未显示)和名称,知乎有2台顶级域的服务器

zhihu.com.		172800	IN	NS	ns3.dnsv4.com.
zhihu.com.		172800	IN	NS	ns4.dnsv4.com.
;; Received 393 bytes from 192.43.172.30#53(192.43.172.30) in 240 ms

# 第四步,向知乎的顶级域服务器(192.43.172.30)请求www.zhihu.com,他发现这个www有个别名,而不是一台主机,别名是eclipse.zhihu.com
www.zhihu.com.		120	IN	CNAME	eclipse.zhihu.com.
eclipse.zhihu.com.	600	IN	A	115.159.241.95
eclipse.zhihu.com.	600	IN	A	115.159.241.25
zhihu.com.		86400	IN	NS	ns4.dnsv4.com.
zhihu.com.		86400	IN	NS	ns3.dnsv4.com.
;; Received 148 bytes from 183.232.90.141#53(183.232.90.141) in 60 ms

参考

(完)~

wks-04:Java快速入门总结

上周技术wks-03:Js this关键字 对Js更近一步认识,这周是Java的试水。

主要参考:Java 语言快速入门

(挖坑,待续~)

git回滚策略

之前总结git 分支的时候,有tag命令

今天看一篇博客传送门觉得他们git处理很值得借鉴,如下图:

GitFlow 流程 :

http://image-2.plusman.cn/image/GitFlowV2.jpg 浏览器打开,查看大图

通过tag 自动回滚

打 tag 的主要目的是什么?最最主要的作用是标记你的每次发布,然后在你发布的过程中如果出现问题了,你可以迅速知道你应该把代码回滚到何处。

# 先列出按照时间倒叙的 tag 列表
git tag -n --sort=-taggerdate
1.0.1-beta.1    考勤成员contact_id保留
1.0.1           考勤成员contact_id保留

# 然后取出第一行
git tag -n --sort=-taggerdate|head -1
1.0.1-beta.1    考勤成员contact_id保留

git tag -n --sort=-taggerdate|head -1|awk '{print $1}'

git reset --hard <tag> # 回滚指定版本

这个很牛逼,比如研究tornado源码的时候可先从简单的v1.0.0看起,那么就可以这样:

$ git clone https://github.com/tornadoweb/tornado.git
$ git reset --hard v1.0.0

(完~)

wks-03:Js this关键字

上周对vim配置和vimscript有一点的了解了:wks-02:Vim配置文件语法学习,这周搞一个我的薄弱点。js this不是新技术了,但是对我来说还是有点陌生的,毕竟用的时候总是模糊的。那么这周就学习搞懂this.

一. 揭秘

Python的selfthis类似,但是Python的self不是关键字,而是一个参数对象,代表实例对象本身。调用实例方法时会隐式传入它,这与Js的this太像了,之前总结过Python的self:Python OOP 常见疑难点汇总

但是Js的this有它特别的地方,JavaScript 的this总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。

也就是说:this是一个对象(环境,运行环境也是对象)。

  • 全局环境中运行,this就是指顶层对象(浏览器中为window对象, 在node下是node宿主环境对象)
  • 在DOM的事件处理,表示当前Dom对象(如文本框)
  • 在一个命名空间或作用域中又是它的对象。
  • ….

就是返回’当前’所在对象的属性或方法。

function f() { return this.name };
var A = {name:'A', callName: f};
var B = {name:'B', callName: f};

console.log(A.callName())   // 'A'
console.log(B.callName())   // 'B'

函数f内部使用了this关键字,随着f所在的对象不同,this的指向也不同, 但无论指向何处都在当前所在的对象下。

比如Dom操作:

<input onChange="valid(this, arg1, arg2)">
<!--回调函数传入this表示当前文本框对象,可用this.value读取输入的值-->

this是所有函数运行时的一个隐藏参数,指向函数的运行环境。

二.this的指向

大致分4类:

  1. 对象方法调用
  2. 函数调用
  3. 构造器调用
  4. Function.prototype.callFunction.prototype.apply调用

第1,2上面已经说了,下面主要看看3,4.

2.1 构造器调用

也就是new 调用函数,返回一个对象,构造器里的this就指向这个返回的对象。如下的一道面试题:

答案如下:

> function obj(name) {
... if (name) {
..... this.name = name;
..... }
... return this;
... }

> obj.prototype.name = "name2";
'name2'
> var a = obj("name1");

> var b = new(obj);

> a.name
'name1'
> b.name
'name2'

还要注意一个问题,如果构造器显式地返回了一个 object 类型的对象,那么最终返回这个对象,可能不是我们期待的 this。解决办法就是绑定this。

> var MyClass = function() {
... this.name = 'jack';
... return {   // 显式返回一个对象
..... name: 'rose'
..... }
... };

> var obj = new MyClass();

> obj.name
'rose'


> var MyClass2 = function() {
... this.name = 'jack';
... return { name: this.name}
... }

> var obj2 = new MyClass2();

> obj2.name
'jack'

2.2 Function.prototype.call 或 Function.prototype.apply

作用:动态地改变传入函数的 this

> var a = {name: 'A', getName: function(){ return this.name }}
> var b = {name: 'B'}
> a.getName()
'A'
> a.getName.call(b);
'B'

三.注意事项

大多数问题出现就是搞不清this的环境,因为this的指向是动态的,所以终极解决方案就是固定this的指向,固定运行环境!, 固定方式如下:

  1. 中间变量
  2. this做参数
  3. call、apply、bind来绑定this

如下需要注意的问题:

  • 避免多层this,在多层下改用一个指向外层this的变量, 如var that = this; 内层引用这个that,也就是使用一个变量固定this的值,嵌套的内层也如此。
  • 避免数组处理方法中的this, 如forEach等.

如下

var o = {
    v: 'v',
    p: ['a', 'b', 'c'],
    f: function() {
        // 解决方案1: 使用中间变量
        var that = this;
        this.p.forEach(function(item) {
            console.log(that.v + ' ' + item);
        })
    }
}

o.f()

var o2 = {
  v: 'v',
  p: ['a', 'b', 'c'],
  f: function(){
    // 解决方案2:this做forEach第二个参数
    this.p.forEach(function(item){
      console.log(this.v + ' ' + item);
    }, this)
  }
}

o2.f()

参考资料

(完~)