• C和指针 第13章 高级指针话题 13.5 字符串常量


    13.5 字符串常量
        当一个字符串常量出现于表达式中,它的值是个指针常量。编译器把这些指定字符的一份副本存储在内存的某个位置,并存储一个指向第一个字符的指针。但是,当数组名用于表达式中时,它们的值也是指针常量。我们可以对它们进行下标引用,间接访问以及指针运算。这些操作对于字符串常量来说是不是也有意义呢?让我们来看一些例子。
        下面这个表达式是什么意思呢?
        "xyz" + 1 
        对于绝大多数程序员而言,它看上去像堆垃圾。它好像是试图在一个字符串上面执行某种类型的加法运算。但是,当你记得字符串常量实际上是个指针时,它的意义就变得清楚了。这个表达式计算“指针值加上1”的值。它的结果是个指针,指向字符串中的第2个字符:y。那么下面这个表达式又是什么呢?
        *"xyz" == 'x';
        对一个指针执行间接访问操作时,其结果就是指针所指向的内容。字符串常量的类型是“指向字符的指针”,所以这个间接访问的结果就是它所指向的字符:x。注意表达式的结果并不是整个字符串,而只是它的第1个字符。
        下一个例子看上去也是有点奇怪,不过现在应该能够推断出这个表达式的值就是字符z:
        *"xyz"[2] == 'z';
        最后这个例子包含了一个错误。偏移量4超出了这个字符串的范围,所以这个表达式的结果是一个不可预测的字符:
        *( "xyz" + 4 )

    /*
    ** 字符串常量。 
    */
    #include <stdio.h>
    #include <stdlib.h>

    int main( void ){
        printf( "\"xyz\" = %p, \"xyz\" = %s\n\"xyz\" + 1 = %p, \"xyz\" + 1 = %s\n", 
        "xyz", "xyz", "xyz" + 1, "xyz" + 1 );
        printf( "*\"xyz\" = %c\n", *"xyz" );
        printf( "\"xyz\"[2] = %c\n", "xyz"[2] );
        /* 
        ** a unpredictable value.
        ** Because "xyz" + 4 is beyond boundary.
        ** *("xyz" + 4)
        */ 
        return EXIT_SUCCESS;
    }
    /* 输出:

    */ 

        什么时候人们可能想使用类似上面这种形式的表达式呢?程序13.4的函数是一个有用的例子。大家都能推断出这个神秘的函数执行了什么任务吗?提示:用几个不同的输入值追踪函数的执行过程,并观察它的打印结果。答案将在本章结束时给出。
        程序13.5包含了一个函数,它把二进制值转换为字符并把它们打印出来。你第一次看到这个函数是在程序7.6中。我们将修改这个例子,以十六进制的形式打印结果值。第一次修改很容易:只要把结果除以16而不是10就可以了。但是,现在余数可能是0~15的任何值,而10~15的值应该以字母A~F来表示。下面的代码是解决这个问题的一种典型方法:
        remainder = value % 16;
        if( remainder < 10 ){
            putchar( remainder + '0' );
        } else{
            putchar( remainder - 10 + 'A' );
        }
        这里使用了一个局部变量来保存余数,而不是3次分别结算它。对于0~9的余数,只需和以前一样打印一个十进制数字。但对于其它余数,就是它们以字母的形式打印出来。代码中的测试是必要的,因为在任何常见的字符集中,字符A~F并不是立即位于数字的后面。
        /*
        **神秘函数。 
        **
        **参数是一个0~100的值。 
        */ 
        #include<stdio.h>
        void mystery( int n ){
            n += 5;
            n /= 10;
            printf( "%s\n", "**********" + 10 - n );
        }
    程序13.4 神秘函数    mystery.c

    /*
    ** 神秘函数。 
    */
    #include <stdio.h>
    #include <stdlib.h>

    void mystery( int n ); 

    int main( void ){
        int i;
        for( i = 5; i <= 100; i += 5 ){
            mystery( i );
        }
        return EXIT_SUCCESS;
    }

    /*
    **神秘函数。 
    **
    **参数是一个0~100的值。 
    */ 
    void mystery( int n ){
        n += 5;
        n /= 10;
        printf( "%s\n", "**********" + 10 - n );
    }
    /* 输出:

    */ 

        /*
        **接受一个整型值(无符号),把它转换为字符,并打印出来。前导零被去除。 
        */ 
        #include<stdio.h>
        void binary_to_ascii( unsigned int value ){
            unsigned int quotient;
            
            quotient = value / 10;
            if( quotient != 0 ){
                binary_to_ascii( quotient );
            } 
            putchar( value % 10 + '0' );
        } 
    把二进制值转换为字符 btoa.c
        下面的代码用一种不同的方法解决这个问题:
        putchar( "0123456789ABCDEF" [value % 16] );
        同样,余数将是一个0~15的值。但这次它使用下标从字符串常量中选择一个字符串进行打印。前面的代码时比较复杂的,因为字符和数字在字符集中并不是相邻的。这个方法定义了一个字符串,使字母和数字相邻,从而避免了这种复杂性。余数将从字符串中选择一个正确的数字。
        第二种方法比传统的方法要快,因为它所需要的操作更少。但是,它的代码并不一定比原来的方法更小。虽然指令减少了,但它付出的代价是多了一个17字节的字符串常量。

    /*
    **接受一个整型值(无符号),把它转换为字符,并打印出来。前导零被去除。 
    */ 
    #include<stdio.h>
    #include<stdlib.h>
     
    void binary_to_dec_ascii( unsigned int value );
    void binary_to_hex_ascii( unsigned int value );
    void binary_to_hex_ascii_2( unsigned int value );

    int main( void ){
        unsigned int value;
        
        value = 34;
        printf( "the dec form of %d is:", value );
        binary_to_dec_ascii( value );
        printf( "\n" );
        printf( "the hex form of %d is:", value );
        binary_to_hex_ascii( value );
        printf( "\n" );
        printf( "the hex form of %d is:", value );
        binary_to_hex_ascii_2( value );
        
        return EXIT_SUCCESS;    
    }

    void binary_to_dec_ascii( unsigned int value ){
        unsigned int quotient;
        
        quotient = value / 10;
        if( quotient != 0 ){
            binary_to_dec_ascii( quotient );
        } 
        putchar( value % 10 + '0' );

    void binary_to_hex_ascii( unsigned int value ){
        unsigned int quotient;
        int remainder;
        
        quotient = value / 16;
        if( quotient != 0 ){
            binary_to_hex_ascii( quotient );
        } 
        remainder = value % 16;
        if( remainder < 10 ){
            putchar( remainder + '0' );
        } else{
            putchar( remainder - 10 + 'A' );
        }

    void binary_to_hex_ascii_2( unsigned int value ){
        unsigned int quotient;
        int remainder;
        
        quotient = value / 16;
        if( quotient != 0 ){
            binary_to_hex_ascii_2( quotient );
        } 
        putchar( "0123456789ABCDEF"[value % 16] );

    /* 输出:

    */ 

        提示:
        但是,如果程序的可读性大幅下降,对于因此获得的执行速度的略微提高是得不偿失的。在使用一种不寻常的技巧或语句时,应确保增加一条注释,描述它的工作原理。一旦解释清楚了这个例子,它实际上就比传统的代码更容易理解,因为它更短一些。
        神秘函数的意思是它根据参数值的一定比例打印相应数量的星号。换句话说,这个函数打印一幅柱状图的一横,它比传统的循环方案要容易得多,效率也高得多。 

  • 相关阅读:
    人工智能对建筑学的影响,关于智能建筑的论文
    产业园区十大企业服务体系!
    10年测试经验,在35岁的生理年龄面前,一文不值
    SSM基于WEB的房屋出租管理系统 毕业设计-附源码261620
    Dubbo的架构设计是怎样的?
    javaFx+google chrome测试下载视频
    LeetCode-3. 无重复字符的最长子串-Java-medium
    一、初始化个人简历项目
    golang gin——controller 模型绑定与参数校验
    linux下的定时任务
  • 原文地址:https://blog.csdn.net/weixin_40186813/article/details/125559833