• 关于数组名与指针的相互转换


    本贴发于CSDN中的C语言讨论区,现转载于此,希望更多的人可以看到,写的不错。

    主要是依据以下关于数组名和指针互相转换的道理:

    (1)当一个数组标识符出现在表达式中,这个标识符的类型就从“某种类型T的数组”转换成“指向类型T的指针”,而且它的值就等于数组第一个元素的地址。并且这个指针是个常量指针,不可改变其值的。
    (2)但是当数组标识符被用作sizeof和取址(&)操作的操作数时,sizeof返回的是整个数组的大小,而取址操作返回的是指向数组的指针(而不是指向一个值为数组头元素地址的指针的指针)。
    (3)既然数组标示符在表达式中被“转换为”指针用,那对于二维数组又是什么情况呢?对于一个二维数组如:int a[3][3], a是指向一维数组的指针;当进行一次a[i]这样的运算后所得到的值是一个指针,其所指对象是一个int类型,[]运算符的作用除了变址,还将一个行指针变为一个列指针;同理当进行一次&a[i]这样的运算后所得到的指针又是一个指向一维数组的指针,即行指针。

        int a[3] = {1, 2, 3};
       
    char **s;
       
    char p[3][5] = {{'a', 'b', 'c', 'c','/0'},
            {
    'd', 'e', 'f', 'f','/0'},
            {
    '/0', '/0', '/0', '/0', '/0'}};

        s
    = (char **)p;

        printf(
    "a: %p/n", a); //0012FF74:a在表达式里被转为int *,指向a[0]
        printf("*&a: %p/n", *&a); //0012FF74:a首先是int *,对一个指针型变量取地址之后再取值就是它本身,所以结果同上一行
        printf("&a: %p/n", &a); //0012FF74:&a返回的是数组指针,因为数组的地址同a[0]的地址,所以结果同上一行
        printf("&a[0]: %p/n", &a[0]); //0012FF74:打印的a[0]同学的地址,所以结果同上一行

        printf(
    "a[0]: %p/n", a[0]);    //00000001:把a[0]的值以双字的形式打印出来
        printf("*a: %p/n", *a); //00000001:把*a里的值当指针打印出其地址。记住a在表达式里被转为int *,指向a[0],
                                       
    //所以*a其实就是a[0],所以结果同上一行。

        printf(
    "p: %p/n", p); //0012FF60:p是指向一维数组的指针,这个语句是要打印该一维数组的地址,等于p[0][0]的地址
        printf("&p: %p/n", &p); //0012FF60:打印二维数组p的地址,等于p[0][0]的地址,所以结果同上一行
        printf("p[0]: %p/n", p[0]); //0012FF60:p[0]是一维数组的数组名,出现在表达式中作为char *使用。
                                       
    //这个语句是要打印p[0]所指向的字符的地址,也就是p[0][0]的地址,所以结果同上一行


        printf(
    "&p[0]: %p/n", &p[0]); //0012FF60:打印一维数组p[0]的地址,等于p[0][0]的地址,所以结果同上一行
        printf("p[1]: %p/n", p[1]); //0012FF65:一维数组名p[1]作为char *,指向p[1][0]。
                                       
    //这个语句是要打印p[1][0]的地址,该地址等于p[0][0]的地址加5


        printf(
    "p[2]: %p/n", p[2]);    //0012FF6A:一维数组名p[2]作为char *,指向p[2][0]。
                                       
    //这个语句是要打印p[2][0]的地址,该地址等于p[1][0]的地址加5


        printf(
    "&p[0][0]: %p/n", &p[0][0]);    //0012FF60:打印p[0][0]的地址
        printf("&p[1][0]: %p/n", &p[1][0]);    //0012FF65:打印p[1][0]的地址
        printf("&p[2][0]: %p/n", &p[2][0]);    //0012FF6A:打印p[2][0]的地址

        printf(
    "s的值: %p/n", s); //0012FF60:s的值等于p的值,因此等于p[0][0]的地址;
        printf("s+1的值: %p/n", s+1); //0012FF64:s是指针的指针,因此s+1等于s的地址加4字节(32位系统);
        printf("*s: %p/n", *s); //63636261:s是char **,*s就是char*。
                                           
    //因此这句意思是把s指向的内存取4个字节(也就是p[0][0]到p[0][]3)作为char*,打印其值。


        printf(
    "以s的值为地址的内存里的内容:%s /n", s); //abcc :从s所指向的地址取出连续内存(遇到'/0'为止)作为字符串来打印。
        printf("以s+1的值为地址的内存里的内容:%s /n", s+1); // :从s+1所指向的地址取字符串来打印。

  • 相关阅读:
    Eclipse快捷键大全
    Quartz任务调度快速入门
    Spring整合logback日志
    Java实现二维码的生成与解析
    跨域问题及解决方案
    SpringBoot项目直接在linux下运行
    SpringBoot拦截器中使用RedisTemplate
    Codeforces Round #345 (Div. 1) C. Table Compression dp+并查集
    HDU 4489 The King’s Ups and Downs dp
    HDU 4747 Mex 递推/线段树
  • 原文地址:https://www.cnblogs.com/pang123hui/p/2309987.html
Copyright © 2020-2023  润新知