我的站点

一个系统软件工程师的随手涂鸦

Month: 九月 2016

理解C语言中关于数组地址值的两个程序

程序1:

#include <stdio.h>

char ga[] = "abcdefghijklm";

void my_array_func(char ca[10]) {
    printf("%#x, %d\n", &ca, sizeof(ca));
    printf("%#x\n", &(ca[0]));
    printf("%#x\n", &(ca[1]));
    printf("%#x\n\n", ++ca);
}

void my_poiner_func(char *pa) {
    printf("%#x, %d\n", &pa, sizeof(pa));
    printf("%#x\n", &(pa[0]));
    printf("%#x\n", &(pa[1]));
    printf("%#x\n\n", ++pa);
}

int main(void) {
    printf("%#x\n", &ga);
    printf("%#x\n", &(ga[0]));
    printf("%#x\n\n", &(ga[1]));
    my_array_func(ga);
    my_poiner_func(ga);
    return 0;
}

运行结果:

0x804987c
0x804987c
0x804987d

0xff95b040, 4
0x804987c
0x804987d
0x804987d

0xff95b040, 4
0x804987c
0x804987d
0x804987d

参考Passing an array as an argument to a function in C

程序2:

#include <stdio.h>

int main(void) {
    // your code goes here
    int array[5];
    printf("%p, %d\n", array, sizeof(array));
    printf("%p, %d\n", &array[0], sizeof(&array[0]));
    printf("%p, %d\n", &array, sizeof(&array));
    printf("%p\n", array + 1);
    printf("%p\n", &array[0] + 1);
    printf("%p\n", &array + 1);
    return 0;
}

运行结果:

0xffd062ec, 20
0xffd062ec, 4
0xffd062ec, 4
0xffd062f0
0xffd062f0
0xffd06300

参考How come an array’s address is equal to its value in C?

再见,H公司

今天是我在H公司工作的最后一天。从20081月毕业以来,这是我第三家公司。与前两次离职是我主动寻求改变不同,这次是由于公司调整,把整个部门关掉了。

我在H公司工作了20个月,是我工作过的三家公司里时间最短的,但是收获却不少。H公司的确是一家很不错的公司,做事厚道,充分尊重员工并给予员工很大的自由度。而我所在的部门更像是一个大学实验室,同事之间关系融洽,有充足的资源和世界上性能最强大的服务器供我学习和使用。现在回头看看,这20个月自身的收获主要有以下几个方面:
(1)Performnace tuning的知识;
(2)操作系统相关知识:主要是Linux kernel开发,此外也接触和使用了FreeBSD
(3)Container技术:学习了DockerMesos的使用,以及Docker SwarmSwarmkit的源代码;
(4)函数式编程的相关知识。

最后,希望H公司可以越来越好!

P.S.,如果您有合适的system/performance software engineer的工作职位,欢迎联系我(nan#chinadtrace.org,把#换成@),谢谢!

Scala笔记(6)——在Scala解释器里退出当前命令

使用scala解释器时,如果中途发现命令输入错误,想退出,可以输入两个“回车”退出当前命令:

scala> val multiline =
 |
 |
You typed two blank lines.  Starting a new command.

Go语言的http.FileServer

看一下下面这段代码:

package main

import (
    "net/http"
)

func main() {
    // To serve a directory on disk (/tmp) under an alternate URL
    // path (/tmpfiles/), use StripPrefix to modify the request
    // URL's path before the FileServer sees it:
    http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
}

(1)http.Dir("/tmp")是利用本地tmp目录实现一个文件系统;
(2)http.FileServer(http.Dir("/tmp"))返回一个Handler,其用来处理访问本地"/tmp"文件夹的HTTP请求;
(3)http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp")))返回一个新的Handler,这个Handler用来处理HTTP请求(移除前缀是"/tmpfiles/"后的URL)。
总结一下,当要访问http://localhost/tmpfiles/a文件,实际访问的是本地/tmp/a文件。

Scala笔记(5)——apply method

本文选自Deeper Look at the Apply Method in Scala

In Scala, there is a language feature generally referred to as “The Apply Method” that has the following rules:

Any object that has an apply method can be called with the .apply omitted.
Functions are no more than objects.

Let’s take a look at an example. Given the following abbreviated definition of class Array, and an instance a,

class Array{
def apply(index:Int) = { …some code to get from the array… }
}

val a = new Array(whatever)

Then the following calls are essentially equivalent:

a.apply(7)
a(7)

Scala笔记(4)——main函数

scala中,main函数必须定义在object中(Java中,main函数必须是class中的static方法):

object Hello extends App{
  override def main(args: Array[String]): Unit = {
    ......
  }
}

或:

object Hello{
  def main(args: Array[String]): Unit = {
    ......
  }
}

其中应用程序的命令行参数通过Array[String]传给main()函数。

什么是“Pure Function”

下列文字摘自The Definition of “Pure Function”

A pure function is a function that depends only on its declared inputs and its internal algorithm to produce its output. It does not read any other values from “the outside world” — the world outside of the function’s scope — and it does not modify any values in the outside world.

1-Pure-Function-Equation

C语言中的“#”和“##”

参考stackoverflow上的这篇帖子

#include <stdio.h>
#define f(a,b) a##b
#define g(a)   #a
#define h(a) g(a)

int main()
{
        printf("%s\n",h(f(1,2)));
        printf("%s\n",g(f(1,2)));
        return 0;
}

运行结果如下:

12
f(1,2)

#a会创建一个字符串:"a"a##b会创建一个新的tokenab。关于macro的处理,参加下列解释:

An occurrence of a parameter in a function-like macro, unless it is the operand of # or ##, is expanded before substituting it and rescanning the whole for further expansion. Because g’s parameter is the operand of #, the argument is not expanded but instead immediately stringified (“f(1,2)”). Because h’s parameter is not the operand of # nor ##, the argument is first expanded (12), then substituted (g(12)), then rescanning and further expansion occurs (“12”).

总结一下,对于function-like macro的参数,如果是#或者##的操作数,则会马上扩展为相应的字符串;否则会先扩展,再替换,循环此操作,直到完成。因此对于g(f(1,2)),会马上替换成"f(1,2)"这个字符串。而对于h(f(1,2)),由于其参数不是#..或者..#..,所以会先把f(1,2)扩展成12,然后替换变成g(12),最后变成"12"

FreeBSD kernel 笔记(13)——delaying execution

4delaying execution方法(选自:FreeBSD Device Drivers):

Sleeping Sleeping is done when you must wait for something to occur before you can proceed.
Event Handlers Event handlers let you register one or more functions to be executed when an event occurs.
Callouts Callouts let you perform asynchronous code execution. Callouts are used to execute your functions at a specific time.
Taskqueues Taskqueues also let you perform asynchronous code execution. Taskqueues are used for deferred work.

Scala笔记(3)——class,object和trait的区别

一言以蔽之,object相当于Java中的singletontrait相当于Java中的interface

参考资料:
Difference between object and class in Scala

Powered by WordPress & Theme by Anders Norén