• C语言疑难进阶手册(1)


    编译

    • 所有源代码文件被编译后,所有目标文件模块便被提交给链接器,链接器分析解释模块之间的引用,从标准运行时函数库中增加函数,检测一般性程序错误。

    词法要素

    • 为了把一个源代码延续到下一行,使用反斜杠在行尾。
    • 标准C引用了宽字符和宽字符串。
    • 宽字符扩展字符集中元素的二进制表示形式。 类型是wchar_t,这个类型是在头文件stddef.h中声明的。
    • c99增加了注释//,在这之前的标准C使用`/**/
    • 整数常量的后缀
      L,l表示long类型
      ll,LL表示 long long类型(C99)
      u,U表示unsigned类型的常量
    • 字符串常量只读的,要修改它只能使用字符数组。字符串常量前面有L表示宽字符串常量
    
    freebsd@localhost:~/learnc % cat learn1.c
    #include 
    #include 
    int main(){
            char*s1="hello,world";
            char s2[]="I love c!";
            wchar_t * s3=L"你好,世界";
          //  s1[3]='x';
            s2[3]='x';
            printf("%s\n",s2);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    
    freebsd@localhost:~/learnc % cc learn1.c
    freebsd@localhost:~/learnc % ./a.out
    I lxve c!
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    s1[3]='x';如去掉注释,程序在运行时将出错,因为s1是只读的。

    
    freebsd@localhost:~/learnc % vim learn1.c
    #include 
    #include 
    int main(){
           char* s="斯柯达";
            printf("%s\n",s);
            char* s1="xxxxxx";
            printf("%s\n",s1);
            return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    
    freebsd@localhost:~/learnc % cc learn1.c -o test
    freebsd@localhost:~/learnc % ./test
    斯柯达
    xxxxxx
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 标识符
      1、标识符区分大小写
      2、标识符无长度限制
      3、关键字不能作标识符
      4、以字母或下划线开头,可以包含字母、数字和下划线。
      5、宏的名字习惯用大写字母

    输入与输出格式串

    • 使用scanf获取输入,使用printf输出
    • 第一个参数使用格式串确定输入与输出的格式
    • scanf遇到不可成功读入的,不再查看格式中的剩余部分,直接返回。
    • 可以不包含格式,仅包含内容,比如
    printf("hello,world");
    
    • 1

    也可以包含格式串和内容

    printf("hello,%s","张三");
    
    • 1

    也就是说第一个参数包含普通字符和转换说明,转换说明以开头。
    %d 有符号十进制整数
    %i 有符号十进制整数
    %u 无符号十进制整数
    %o 八进制整数
    %x 十六进制整数(小写字母)
    %X 十六进制整数(大写字母)
    %f 浮点数
    %e 用科学计数法表示的浮点数(小写字母e)
    %E 用科学计数法表示的浮点数(大写字母E)
    %g 根据数值的大小自动选择%f或%e格式
    %G 根据数值的大小自动选择%f或%E格式
    %c 单个字符
    %s 字符串
    %p 指针地址
    %n 将已打印字符数保存在整型指针中
    %% 打印一个百分号
    转换说明在表示数字时,可指定宽度等。

    %a.bf表示最小宽度为a,小数为b位,浮点数。

    注释

    c99之前,不使用//

    字符常量

    单字符常量的类型是int
    sizeof(char)等于sizeof(int)

    宏与预处理器

    • 不对源文本进行解析。
    • #开始的行是预处理命令。
    • define命令有两种:
    #define 名称 标记
    
    • 1

    名称为宏名,标记为宏体。

    比如

    #include 
    #define MYHELLO "你好,世界\n"
    int main(int argc, char **argv)
    {
    	printf(MYHELLO );
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    #include 
    #define PT printf
    int main(int argc, char **argv)
    {
    	PT ("hello\n" );
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    第二种要复杂一些,在宏体中使用括号,这叫做带参数的宏。

    #include 
    #define PT(helloStr) printf(helloStr)
    int main(int argc, char **argv)
    {
    	PT ("hello,world\n" );
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    格式为

    #define 名称(标识符列表) 标记
    
    • 1

    标识符列表为参数列表,多个参数用分隔

    #include 
    #define PT(helloStr,n) printfn(helloStr,n)
    void printfn(char *helloStr,int n){
        for (int  i=0;i<n;i++){
            printf(helloStr);
        }
    }
    int main(int argc, char **argv)
    {
    	PT ("hello,world\n",5 );
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    hello,world
    hello,world
    hello,world
    hello,world
    hello,world
    Hit any key to continue...
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    要注意防止隐含在宏中的错误。

    #include 
    #define SUM(x1,x2,x3,n)  x1*n+x2*n+x3*n
    int main(int argc, char **argv)
    {
    	printf ("%d\n",SUM(1,,3,4) );
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    上面程序初看没问题
    运行结果也正常
    但尝试给宏SUM传入以下参数,就会遇到错误

    #include 
    #define SUM(x1,x2,x3,n)  x1*n+x2*n+x3*n
    int main(int argc, char **argv)
    {
    	printf ("%d\n",SUM(1+1,1+2,1+3,4) );
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    27
    Hit any key to continue...
    
    
    • 1
    • 2
    • 3

    结果应是2*4+3*4+4*4=8+12+16=36
    下面程序才是正确的,括号是必须要加的

    #include 
    #define SUM(x1,x2,x3,n)  ((x1)*(n)+(x2)*(n)+(x3)*(n))
    int main(int argc, char **argv)
    {
    	printf ("%d\n",SUM(1+1,1+2,1+3,4) );
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 宏表达式扫描
      宏调用展开后,对宏表达式的扫描在宏展开的开始位置继续,宏替换不是在#define语句部分进行的,在处理宏展开时执行。
  • 相关阅读:
    Java反射,看完就会用
    Kubernetes 进阶训练营 控制器
    RStudio中利用Project与Git实现版本控制
    C#的多线程UI窗体控件显示方案 - 开源研究系列文章
    【算法题解】拓扑序计数+树形DP
    Spring中的设计模式
    Element-ui 动态tabs实战
    工程伦理--13.1 什么是“邻避效应”?
    【C/C++笔试练习】二维数组、二维数组的访问,解引用,地址计算、计算糖果、进制转换
    js去除数组对象中的重复对象
  • 原文地址:https://blog.csdn.net/AI_LX/article/details/130799752