# C进阶指南（2）：数组和指针、打桩

2016-12-14 09:53:04来源:http://blog.csdn.net/To_Be_IT_1/article/details/37652253作者:To_Be_IT_1人点击

## 三、指针和数组

6.3.2.1小节：

`short a[] = {1,2,3};short *pa;short (*px)[];void init(){    pa = a;    px = &a;    printf("a:%p; pa:%p; px:%p/n", a, pa, px);    printf("a[1]:%i; pa[1]:%i (*px)[1]:%i/n", a[1], pa[1], (*px)[1]);}`

（译者注：%i能识别输入的八进制和十六进制）

aint型数组，pa是指向int的指针，px是个未完成的、指向数组的指针。a赋值给pa前，它的值被转为一个指向数组开头的指针。右值表达式&a并非意味着指向int，而是一个指针，指向int型数组因为当使用一元符号&时右值不被转换为指针。

`int a[];int *pa;`

`extern int *a;extern int pa[];`

### 3.1 数组作为函数形数

`void sum(int data[10]) {}void sum(int data[]) {}void sum(int *data) {}`

`typedef int[4] vector;vector m[2] = {{1,2,3,4}, {4,5,6,7}};int n[2][4] = {{1,2,3,4}, {4,5,6,7}};`

`int *p = n[1];int y = p[2];`

`int z = *(*(n+1)+2);`

`int x = n[1][2];`

`void sum(int data[2][4]) {}void sum(int data[][4]) {}void sum(int (*data)[4]) {}`

`void list(int *arr, int max_i, int max_j){    int i,j;    for(i=0; i        for(j=0; j            int x = arr[max_i*i+j];            printf("%i, ", x);        }        printf("/n");    }}`

`int main(int argc, char **argv){    int arr1[4] = {1,2,3,4};    int arr2[4] = {5,6,7,8};    int *arr[] = {arr1, arr2};    list(arr, 2, 4);}void list(int **arr, int max_i, int max_j){    int i,j;    for(i=0; i        for(j=0; j            int x = arr[i][j];            printf("%i, ", x);        }        printf("/n");    }}`

`const char *strings[] = {    "one",    "two",    "three"};`

`void list(int max_i, int max_j, int arr[][max_j]){    /* ... */    int x = arr[1][3];}`

`static void catch_int(int no) {    /* ... */};int main(){    signal(SIGINT, catch_int);    /* ... */}`

## 四、打桩（Interpositioning）

`/* _GNU_SOURCE is needed for RTLD_NEXT, GCC will not define it by default */#define _GNU_SOURCE#include #include #include #include #include static uint32_t malloc_count = 0;static uint64_t total = 0;void summary(){    fprintf(stderr, "malloc called: %u times/n", count);    fprintf(stderr, "total allocated memory: %" PRIu64 " bytes/n", total);}void *malloc(size_t size){    static void* (*real_malloc)(size_t) = NULL;    void *ptr = 0;    if(real_malloc == NULL){        real_malloc = dlsym(RTLD_NEXT, "malloc");        atexit(summary);    }    count++;    total += size;    return real_malloc(size);}`

RTLD_NEXT 伪处理程序到 dlsym，我们获得了指向下一个已加载的链接库中 malloc 事件的指针。第一次 malloc 调用 libc 的 malloc，当程序终止时，会调用由 atexit 注册的获取和summary函数。看GNU/Linxu中打桩行为（真的184次调用！）：

`\$ gcc -shared -ldl -fPIC malloc_counter.c -o /tmp/libmcnt.so\$ export LD_PRELOAD="/tmp/libstr.so"\$ ps  PID TTY          TIME CMD 2758 pts/2    00:00:00 bash 4371 pts/2    00:00:00 psmalloc called: 184 timestotal allocated memory: 302599 bytes`

### 4.1 符号可见性

`#if __GNUC__ >= 4 || __clang__  #define EXPORT_SYMBOL __attribute__ ((visibility ("default")))  #define LOCAL_SYMBOL  __attribute__ ((visibility ("hidden")))#else  #define EXPORT_SYMBOL  #define LOCAL_SYMBOL#endif`