c语言 指针与数组

关键概念

1.多个不同类型的指针可以对应同一个地址;

2.(&p)则是这样一种运算,返回一个指针,该指针的值是当时声明p 时开辟的地址,指针的类型是p的类型对应的指针类型;

3.(*p)操作是这样一种运算,获取指针p的值(变量的地址)找到对应的变量的值-----返回以(p 的值作为地址)的那个空间的值。但是如果这个变量本身就是一个地址,那么(*p)获取的值也是一个指针

数组关键知识点

a.当数组名参与数学计算时,数组名会从"T类型的数组"转换成"指向类型T的指针",此时数组名是常量指针,不可改变其值。

b.数组名在 sizeof, 下标计算[], 取址&等操作的操作数时,是作为T类型的数组而存在的

一维数组

#include<stdio.h>
#include<stdlib.h>

void test()
{
    int arr[5] = { 1,2,3,4,5 };

    int* p = arr;

    // 赋值操作,方便观察
    for (int i = 0; i < 5; i++)
    {
        printf(" %d:%p ", arr[i], &arr[i]);
    }
    printf("\n");

    /*
    设计说明:
        arr+1分析
        arr+1符合数组关键知识点a,arr参与数学计算时,arr的类型转变成 int*
        arr的步长是sizeof(int*),即4
        假设arr的指针值是0x87f904,那么arr+1对应的指针值是0x87f918
    */
    printf("arr = %p, arr + 1 = %p\n", arr, arr + 1);

    /*
    设计说明:
        &arr分析
        &arr符合数组关键知识点b,arr此时的数据类型是 int k[5]
        &arr的数据类型是数组指针,即 int (*k)[5]

        &arr的步长是sizeof(int k[5]),即20

        假设arr的指针值是0x87f904,那么&arr+1对应的指针值是0x87f908
    */
    printf("arr = %p, &arr + 1 = %p\n", arr, &arr + 1);

    /*
    设计说明:
        arr[x]分析
        arr[x]符合数组关键知识点b,arr此时的数据类型是 int k[5]
        arr[x]即取数组类型的第x个元素

        arr[x] 等价于 *(arr + x)
        在*(arr + x)表达式中,arr的数据类型是int *
    */
    printf("arr[1] = %d, *(arr + x) = %d\n", arr[1], *(arr + 1));

}

void main() 
{
    test();
    system("pause");

}

二维数组

#include<stdio.h>
#include<stdlib.h>


void test()
{
    int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };

    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            printf(" %d ", arr[i][j]);
        }
        printf("\n");
    }

    /*
    设计说明:
        arr+1分析
        arr+1符合数组关键知识点a,arr参与数学计算时,arr的类型转变成 int (*m)[4],即数组指针类型
        arr的步长是sizeof(int m[4]),即16

        假设arr的指针值是0x87f904,那么arr+1对应的指针值是0x87f914
    */
    printf("arr = %p, arr + 1 = %p\n", arr, arr + 1);

    /*
    设计说明:
        &arr分析
        &arr符合数组关键知识点b,arr此时的数据类型是 int n[3][4],即二维数组类型
        &arr的数据类型是二维数组指针,即 int (*n)[3][4]

        &arr的步长是sizeof(int n[3][4],),即48

        假设arr的指针值是0xd7a4f6f758,那么&arr+1对应的指针值是0xd7a4f6f788
    */
    printf("arr = %p, &arr + 1 = %p\n", arr, &arr + 1);

    /*
    设计说明:
        arr[x][y]分析
        arr[x][y]符合数组关键知识点b,arr此时的数据类型是 int n[3][4],即二维数组类型
        arr[x][y]即取数组类型的第x行,第y列的元素

        arr[x][y] 转换逻辑详解
        arr+x 此时arr的类型是 int (*m)[4],arr的步长是20
        *(arr+x)的类型是int *类型
        
        为啥*(arr+x)的类型不是一维数组类型(int m[4])呢?
            因为根据数组关键知识点a,在数学计算中,数组名都会转换为指向类型T的指针
            *(arr+x)本身的类型是数组类型,在此表达式中转换成int*

        *(*(arr+x)+y)的类型是int类型
    */
    printf("arr[1][2] = %d, *(*(arr+1)+2) = %d\n", arr[1][2], *(*(arr + 1) + 2));

}


void main()
{
    test();
    system("pause");
}

 

数组做参数

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>


void run1(int* p) 
{
    // 指针大小是4个字节,没有疑问
    printf("run1: sizeof(p)=%lld\n", sizeof(p));//结果是4
    printf("run1: p[0]=%d\n", p[0]);
}

void run2(int p[5])
{
    //当数组类型变量当作函数参数的时候会转换为指向类型T的指针

    // 这里p的数据类型是int*
    printf("run2: sizeof(p)=%lld\n", sizeof(p));//结果是4

    // 发现p的步长是4,进一步验证p的数据类型是int*
    printf("run2: p=%p, p+1=%p\n", p, p + 1);
    printf("run2: p[0]=%d\n", p[0]);
}

void main() 
{
    int a[5] = { 1, 2, 3, 4, 5 };

    run1(a);
    run2(a);

    system("pause");
}

 

posted on 2016-01-12 15:36  寒魔影  阅读(429)  评论(0编辑  收藏  举报

导航