2011年11月20日日曜日

[C 语言] 指针

 http://murakan.cocolog-nifty.com/blog/2011/08/cc-b731.html
http://www.aso.ecei.tohoku.ac.jp/~shun/multi_dim.html
 
1. 用指针代替数组好处
1-1. 节省内存使用
     数组每行元素要保留最大元素的长度
     而指针只保留每个元素实际长度
1-2. 作为函数参数, 在函数中访问并可以修改 (地址传递)
1-3. 将数组定义为字符串
1-4. 在结构体中使用
------------------------------------------------------------

2. 字符串与指针的关系
2-1. 字符串可以定义为字符数组 char str[], 也可以定义为字符指针 char *str, 相当于指针数组, str 中存储字符串第一个字符的地址
#include<stdio.h>
main()
{
    char *c = "12345";   /* 正确 */
    int  *i = "12345";   /* 错误, 只能定义字符串 */
    char *c; c ="12345"; /* 初始化错误 */
    printf("%s",c);
}

2-2. 将字符串定义为指针数组, 可以直接进行指针运算
#include<stdio.h>
main()
{
    char *str ="12345";
    for(;*str!='\0';str+=1)
    printf("%s\n",str); /* 直接将指针变量转换为值 */
}
------------------------------------------------------------

3. 将数组传递给函数
3-1. 数组变量的传递
#include<stdio.h>
main()
{
    int i[]={1,2};
    int ans;
    ans=func(i);
}

int func(int x[])
{
    return (x[0] * x[1]);
}

3-2. 数组指针的传递
#include<stdio.h>
main()
{
    int i[]={1,2};
    int ans;
    ans=func(i); /* i 代表数组 i[] 起始地址 */
}

int func(int *x)
{
    return (*x * *(x+1));
}
------------------------------------------------------------

4. 一维数组与指针的关系
#include<stdio.h>
main()
{
    int i,arr[] = {0,1,2,3,4,5,6,7,8,9};
    int *point;

    point = arr;
    for(i=0;i<10;i++){
        printf("&arr[%d] = %p arr[%d] = %d ",i,&arr[i],i,arr[i]);
        printf("point+%d = %p *(point+%d) = %d\n",i,point+i,i,*(point+i));
    }
}

point+i = point (arr的开始地址) + size (指针类型) * i
地址 : &arr[i] = point+i
元素 : arr[i]  = *(point+i)
------------------------------------------------------------

5. 二维数组与指针
5-1.
#include<stdio.h>
main()
{
    int matrix[2][3] = {{1,2,3},{4,5,6}};

    printf("matrix[0][0] = %d\n",**matrix        );
    printf("matrix[0][1] = %d\n",*(*matrix+1)    );
    printf("matrix[0][2] = %d\n",*(*matrix+2)    );
    printf("matrix[1][0] = %d\n",**(matrix+1)    );
    printf("matrix[1][1] = %d\n",*(*(matrix+1)+1));
    printf("matrix[1][2] = %d\n",*(*(matrix+1)+2));

    printf(" &matrix[0][0] = %d\n",&matrix[0][0]);
    printf(" &matrix       = %d\n",&matrix);
    printf("  matrix       = %d\n",matrix);
    printf(" *matrix       = %d\n",*matrix);
    printf("**matrix       = %d\n",**matrix);

    printf("&matrix[0][0]+1 = %d\n",&matrix[0][0]+1);
    printf("&matrix+1       = %d\n",&matrix+1);
    printf(" matrix+1       = %d\n",matrix+1);
    printf("*matrix+1       = %d\n",*matrix+1);
}

指针p, 不能访问 matrix
int **point;
point=matrix;

 &matrix : 行列开始处的地址
  matrix : 第一行开头的地址
 *matrix : 第一列开头的地址
**matrix : 元素的值
此时, &matrix = matrix = *matrix

指针 + 1 之后的情况
 &matrix+1 : 行列结尾的下一个地址(+24)
  matrix+1 : 下一行的开始地址(+12)
 *matrix+1 : 下一个元素的地址(+4)

5-2. 二维数组的指针访问
5-2-1. 数组的指针 (适合访问处理)
#include <stdio.h>
int main()
{
    int data[][3] = {{1, 2, 3}, {4, 5, 6}};
    int (*dPtr)[3] = data;

    printf("data[0][0] = %d\n", dPtr[0][0]);
    printf("data[0][1] = %d\n", dPtr[0][1]);
    printf("data[0][2] = %d\n", dPtr[0][2]);
    printf("data[1][0] = %d\n", dPtr[1][0]);
    printf("data[1][1] = %d\n", dPtr[1][1]);
    printf("data[1][2] = %d\n", dPtr[1][2]);

    return 0;
}

内存形态如下:
dPtr          data[2][3]
+-----+      +-----------+
|&data|----->| 1 | 2 | 3 |
+-----+      |-----------|
             | 4 | 5 | 6 |
             +-----------+

5-2-2. 指针数组 (适合排序处理)
#include<stdio.h>
int main(){
    int matrix[2][3]={ {1, 2, 3}, {4, 5, 6} };
    int *point[2];
    point[0]=matrix[0];
    point[1]=matrix[1];

    printf("matrix[0][0] = %d\n",point[0][0]);
    printf("matrix[0][1] = %d\n",point[0][1]);
    printf("matrix[0][2] = %d\n",point[0][2]);
    printf("matrix[1][0] = %d\n",point[1][0]);
    printf("matrix[1][1] = %d\n",point[1][1]);
    printf("matrix[1][2] = %d\n",point[1][2]);

    return 0;
}

内存形态:
point[2]        matrix[2][3]
+-------+      +-----------+
|data[0]|----->| 1 | 2 | 3 |
+-------+      |-----------|
|data[1]|----->| 4 | 5 | 6 |
+-------+      +-----------+

5-3. 二维数组函数参数传递
void fa (int a[][5]);
main ()
{
    int a[3][5] = { ... };
    fa(a); /* 指针传递 */
}

void fa(int a[][5]) /* 5 必须 */
{ ... }
------------------------------------------------------------

6. 指针的指针
#include<stdio.h>
main()
{
    int i=10;
    int *p;
    int **point;

    p=&i;
    point=&p;

    printf("      i = %d\n",i);
    printf("     *p = %d\n",*p);
    printf("**point = %d\n",**point);
    printf("     &i = %p\n",&i);
    printf("      p = %p\n",p);
    printf(" *point = %p\n",*point);
    printf("     &p = %p\n",&p);
    printf("  point = %p\n",point);
    printf(" &point = %p\n",&point);
}

|---------|------|----------------|-------------|
|地址     |变量  |值              |访问         |
|0064FE00 |i     |10(10进制)      |i,*p,**point |
|0064FDFC |p     |64FE00(16进制)  |&i,p,*point  |
|0064FDF8 |point |64FDFC(16进制)  |&p,point     |
|---------|------|----------------|-------------|
------------------------------------------------------------

7. 指针函数 (返回值是指针的函数)
#include <stdio.h>
char *string_func(int n);
int *int_func(int);
main()
{
    int i;
    for ( i=1;i<=3;i++){
        printf("String No.%d %s\n",i,string_func(i));
    }

    printf(" int_func(30) value = %d\n",int_func(30));
    printf("*int_func(30) value = %d\n",*int_func(30));

    return 0;
}

char *string_func(int n)
{
    static char *string[] = {
        "",
        "C-Production",
        "Official HomePage",
        "Spring Version"
    };
    return string[n];
}

int *int_func(int n)
{
    int *integer;
    integer = &n;
    return integer;
}

结果
String No.1 C-Production
String No.2 Official HomePage
String No.3 Spring Version
 int_func(30) value = 6618624
*int_func(30) value = 30
------------------------------------------------------------

8 函数的指针
8-1 用函数指针调用函数
#include <stdio.h>
void func(int);

int main()
{
    void (*P_func)(int);
    P_func = func;
    (*P_func)(1);
    return 0;
}

void func(int i)
{
    printf("%d",i);
    return;
}

8-2 函数指针与数组结合
#include<stdio.h>
int and(int x,int y);
int or(int x,int y);
void main()
{
    int (*p_func[2])(int x,int y);
    int i,j,k;

    p_func[0] = and;
    p_func[1] = or;

    printf("x  y  AND  OR\n");
    for(i=0;i<2;i++){
        for(j=0;j<2;j++){
            printf("%d  %d  ",i,j);
            for(k=0;k<2;k++){
                printf(" %d  ",(*p_func[k])(i,j));
            }
            printf("\n");
        }
    }
}

int and(int x, int y)
{
    return x&&y;
}

int or(int x, int y)
{
    return x||y;
}

結果
x  y  AND  OR
0  0   0   0
0  1   0   1
1  0   0   1
1  1   1   1
------------------------------------------------------------

9. 指针函数的指针 (指向返回值为指针的函数的指针)
#include <stdio.h>
char *string_func(int n);

int main()
{
    int i;
    char *(*P_func)(int);
    P_func = string_func;

    for ( i=1;i<=3;i++){
        printf("String No.%d %s\n",i,(*P_func)(i));
    }
    return 0;
}

char *string_func(int n)
{
    static char *string[] = {
        "",
        "C-Production",
        "Official HomePage",
        "Spring Version"
    };
    return string[n];
}

0 件のコメント:

コメントを投稿