浏览模式: 普通 | 列表

字符串编码转换

[ 2009-12-22 15:34:46 | 作者: yuhen ]
iconv 做字符串编码转换很方便很强大。
#include <iconv.h>

size_t iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);

参数说明:
  • inbuf: 源字符串
  • inbytesleft: 源字符串中没有被转换的字节数
  • outbuf: 目标存储缓存
  • outbytesleft: 目标缓存剩余空间
需要注意的是 inbuf 和 outbuf 接受的不是数组指针,因此不能直接 "&数组名"。
#include <stdio.h> 
...

阅读全文…

安装 C Library Manpages

[ 2009-12-18 09:36:01 | 作者: yuhen ]
虽然比不上 MSDN 豪华,但也是日常开发离不了的东西。
sudo apt-get install manpages-dev

然后就可以用如下命令查看标准库函数手册了
$ man 3 <function>

如: man 3 printf

还可以用 -k 参数搜索所有相关的信息
$ man -k printf

asprintf (3)         - print to allocated string
dprintf (3)          - print to a file descriptor
fprintf (3)          - formatted output conversion
fwprintf (3)         - formatted wide-character output conversion
...

阅读全文…

C 函数传出参数

[ 2009-12-17 05:28:36 | 作者: yuhen ]
所谓传出参数是指我们非但可以修改参数对象成员,还可以将实参重新指向新的对象。
#include <stdio.h>

void test(char *s)
{
    s = "Test...";
}

int main(void)
{
    char *s = "Hello";

    test(s);
    printf("%s\n", s);                                                                       
  
    return 0;
}

输出:
Hello

函数 test 的修改之所以无效,是应为 "指针(引用)本身同样是按值拷贝传递的"。这在 C# 中早有前例,也是 ref 的作用。我们具体分析一下。
$ objdump -dS -M intel test | less
...

阅读全文…

Ubuntu Server 9.10 安装 Mono 2.4 运行环境

[ 2009-12-16 07:50:25 | 作者: yuhen ]
$ sudo apt-get install mono-gmcs libmono-system-data2.0-cil libmono-system-ldap2.0-cil libmono-system-messaging2.0-cil libmono-system-runtime2.0-cil libmono-system-web2.0-cil libmono-system-web-mvc1.0-cil libmono-wcf3.0-cil libmono-winforms2.0-cil

可选:
libmono-oracle2.0-cil libmono-npgsql2.0-cil libmono-nunit2.4-cil libmono-sharpzip2.84-cil libmono-sqlite2.0-cil

安装信息:
...

阅读全文…

Linux 进程内存模型 (2)

[ 2009-12-11 09:03:52 | 作者: yuhen ]
接下来我们分析不同生存周期变量在进程空间的位置。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

int x = 0x1234;
char *s;

int test()
{
    static int a = 0x4567;
    static int b;

    return ++a;
}

int main(int argc, char* argv[])
{
    int i = test() + x;
    s = "Hello, World!";

    char* p = malloc(10);

    return EXIT_SUCCESS;
}

在分析 ELF 文件结构时我们就已经知道全局变量和静态局部变量在编译期就决定了其内存地址。

...

阅读全文…

Linux 进程内存模型 (1)

[ 2009-12-11 08:30:05 | 作者: yuhen ]
下图是一个简易的内存模型示意图。其中某些段 (Segment) 是从可执行文件加载的,有关 ELF Section 和 Segment 的映射关系,我们可以从 ELF Program Headers 中获取相关信息。

uploads/200912/11_083011_1.png

$ readelf -l hello

Elf file type is EXEC (Executable file)
Entry point 0x8048410
There are 8 program headers, starting at offset 52

Program Headers:
    Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
...

阅读全文…

C 指针概要

[ 2009-12-08 22:31:54 | 作者: yuhen ]
简单罗列一下 ANSI C 的指针用法,便于复习。

1. 指针常量

指针常量意指 "类型为指针的常量",初始化后不能被修改,固定指向某个内存地址。我们无法修改指针自身的值,但可以修改指针所指目标的内容。
int x[] = { 1, 2, 3, 4 };
int* const p = x;

int i = 0;
for (i = 0; i < 4; i++)
{
    int v = *(p + i);
    *(p + i) = ++v;

    printf("%d\n", v);

    //p++;  // Compile Error!                                                             
}

上例中的指针 p 始终指向数组 x 的第一个元素,和数组名 x 作用相同。由于指针本身是常量,自然无法执行 "p++"、"++p" 之类的操作,否则会导致编译错误。
...

阅读全文…

GCC 的 "智慧"

[ 2009-12-07 19:22:43 | 作者: yuhen ]
我们看一下 GCC 默认优化模式下的 "智慧"。
void inc(int* x)
{
    *x += 1;                                                                                 
}

int main(void)
{
    int i = 2;
    inc(&i);
}

反编译
(gdb) disass inc
Dump of assembler code for function inc:

0x08048488 <inc+0>:    push   ebp
0x08048489 <inc+1>:    mov    ebp,esp
0x0804848b <inc+3>:    mov    eax,DWORD PTR [ebp+0x8] ;载入 x 内容,也就是 i 的地址
...

阅读全文…