精华内容
下载资源
问答
  • 本文和大家分享的主要是c语言预编译指令相关内容,一起来看看吧,希望对大家学习c语言有所帮助。  预处理器的主要作用就是把通过预处理的内建功能对一个资源进行等价替换,最常见的预处理器指令有:文件包含、...
    本文和大家分享的主要是c语言中预编译指令相关内容,一起来看看吧,希望对大家学习c语言有所帮助。
      预处理器的主要作用就是把通过预处理的内建功能对一个资源进行等价替换,最常见的预处理器指令有:文件包含、条件编译、布局控制和宏替换4种。
      文件包含
      #include是一种最为常见的预处理,作为文件的引用。
      条件编译
      #if#ifndef等,主要是进行预编译时进行有选择的挑选,注释掉一些指定的代码,以达到版本控制、防止对文件重复包含的功能。
      布局控制
      #pragma,这也是我们应用与处理的一个重要部分,主要功能是为编译程序提出非常规的控制流信息。
      宏替换
      #define,这是最常用的用法,它可以定义符号常量、函数功能、重新命名、字符串的拼接等各种功能。
      常见的预处理指令
      #define宏定义
      #undef未定义宏
      #include文本包含
      #ifdef如果宏被定义就进行编译
      #ifndef如果宏未被定义就进行编译
      #endif结束编译块的控制
      #if表达式非零就对代码进行编译
      #else
      #elif这是一种#else#if的组合选项
      #line改变当前的行数和文件名称
      #error输出一个错误信息
      #pragma为编译程序提供非常规的控制流信息。
      预定义标识符
      为了处理一些有用的信息,预处理定义了一些预处理标识符,虽然各种编译器的预处理标识符不尽相同,但他们都会处理下面四种:
      __FILE__:正在编译的文件名
      __LINE__:正在编译的文件的行号
      __DATE__:编译时刻的日期字符串
      __TIME__:编译时刻的时间字符串
      注意:
      #include
      编译器从标准库路径开始搜索。
      #include “stdio.h”
      编译器从用户的工作路径开始搜索。
      #error this code is c,
      not python.
      在预编译时,会报错,如上信息。
    来源:简书
    展开全文
  • 问关于C语言中的预处理命令 答 我们可以在C 源程序中插入传给 编译程序的各种指令这些指令被称为处理器指令等价于汇编语言中的伪指令它们扩充了程序设计的环境 现把常用的 预处理命令总结如下 1. 预处理程序 按照...
  • 问关于 C 语言中的预处理命令 答 我们可以在 C 源程序 中插入传给 编译程序 的各种指令这些指令被称为 处理器指令等价于 汇编语言中的伪指令 它们扩充了程序设计的环境 现把常用的 预处理命令 总结如下 预处理程序...
  • 问关于 C 语言中的预处理命令 答 我们可以在 C 源程序 中插入传给 编译程序 的各种指令这些指令被称为 处理器指令等价于 汇编语言中的伪指令 它们扩充了程序设计的环境 现把常用的 预处理命令 总结如下 1....
  • c语言中预处理命令都有哪些

    千次阅读 2013-04-23 21:17:29
    按照ANSI标准的定义,预处理程序应该处理以下指令: ...我们可以在C源程序中插入传给编译程序的各中指令,这些指令被称为处理器指令,它们扩充了程序设计的环境。现把常用的预处理命令总结如下: 1. 

    按照ANSI标准的定义,预处理程序应该处理以下指令:
    #if
    #ifdef
    #ifndef
    #else
    #elif
    #endif
    #define
    #undef
    #line
    #error
    #pragma
    #include

    我们可以在C源程序中插入传给编译程序的各中指令,这些指令被称为预处理器指令,它们扩充了程序设计的环境。现把常用的预处理命令总结如下: 
    1.      预处理程序
    按照ANSI标准的定义,预处理程序应该处理以下指令:
    #if #ifdef #ifndef #else #elif
    #endif
    #define
    #undef
    #line
    #error
    #pragma
    #include
    显然,上述所有的12个预处理指令都以符号#开始,,每条预处理指令必须独占一行。
    2.      #define
    #define指令定义一个标识符和一个串(也就是字符集),在源程序中发现该标识符时,都用该串替换之。这种标识符称为宏名字,相应的替换称为宏代换。一般形式如下:
    #define macro-name char-sequence
    这种语句不用分号结尾。宏名字和串之间可以有多个空白符,但串开始后只能以新行终止。
    例如:我们使用LEFT代表1,用RIGHT代表0,我们使用两个#define指令:
    #define LEFT 1
    #define RIGHT 0
    每当在源程序中遇到LEFT或RIGHT时,编译程序都用1或0替换。
    定义一个宏名字之后,可以在其他宏定义中使用,例如:
    #define ONE 1
    #define TWO ONE+ONE
    #define THREE ONE+TWO
    宏代换就是用相关的串替代标识符。因此,如果希望定义一条标准错误信息时,可以如下定义:
    #define ERROR_MS “Standard error on input \n”
    如果一个串长于一行,可在行尾用反斜线”\”续行,如下:
    #define LONG_STRING “This is a very very long \
    String that is used as an example”
    3.      #error
    #error指令强制编译程序停止编译,它主要用于程序调试。#error指令的一般形式是:
    #error error-message
    注意,宏串error-message不用双引号包围。遇到#error指令时,错误信息被显示,可能同时还显示编译程序作者预先定义的其他内容。
    4.      #include
    程序中的#include指令要求编译程序读入另一个源文件。被读入文件的名字必须用双引号(“”)或一对尖括号(<>)包围,例如:
    #include “stdio.h”
    #include <stdio.h>
    都使C编译程序读入并编译头文件以用于I/O系统库函数。
    包含文件中可以包含其他#include指令,称为嵌套包含。允许的最大嵌套深度随编译器而变。
    文件名被双括号或尖括号包围决定了对指定文件的搜索方式。文件名被尖括号包围时,搜索按编译程序作者的定义进行,一般用于搜索某些专门放置包含文件的特殊目录。当文件名被双括号包围时,搜索按编译程序实时的规定进行,一般搜索当前目录。如未发现,再按尖括号包围时的办法重新搜索一次。
    通常,绝大多数程序员使用尖括号包围标准的头文件,双引号用于包围与当前程序相关的文件名。
    
    5.      条件编译指令
    若干编译指令允许程序员有选择的编译程序源代码的不同部分,这种过程称为条件编译。
    5.1#if、#else、#elif #endif
    条件编译指令中最常用的或许是#if,#else,#elif和#endif。这些指令允许程序员根据常数表达式的结果有条件的包围部分代码。
    #if的一般形式是:
    #if constant-expression
    Statement sequence
    #endif
    如#if后的常数表达式为真,则#if和#endif中间的代码被编译,否则忽略该代码段。#endif标记#if块的结束。
    #else指令的作用与C语言的else相似,#if指令失败时它可以作为备选指令。例如:
    #include <stdio.h>
    #define MAX 100
    Int main(void)
    {
    #if MAX>99
    printf(“Compiled for array greater than 99.\n”);
    #else
    printf(“Complied for small array.\n”);
    #endif
    return 0;
    }
    注意,#else既是标记#if块的结束,也标记#else块的开始。因为每个#if只能写一个#endif匹配。
    #elif指令的意思是“否则,如果”,为多重编译选择建立一条if-else-if(如果-否则-如果链)。如果#if表达式为真,该代码块被编译,不测试其他#elif表达式。否则,序列中的下一块被测试,如果成功则编译之。一般形式如下:
    #if expression
    Statement sequence
    #elif expression1
    Statement sequence
    #elif expression2
    Statement sequence
    .
    .
    .
    #elif expression
    Statement sequence
    #endif
    5.2#ifdef和#ifndef
    条件编译的另一个方法是使用编译指令#ifdef和#ifndef,分别表示“如果已定义”和“如果未定义”。#ifdef的一般形式如下:
    #ifdef macro-name
    Statement sequence
    #endif
    如果macro-name原先已经被一个#define语句定义,则编译其中的代码块。
    #ifndef的一般形式是:
    #ifndef macro-name
    Statement sequence
    #endif
    如果macro-name当前未被#define语句定义,则编译其中的代码块。
    
    我认为,用这种,可以很方便的开启/关闭整个程序的某项特定功能。
    #ifdef和#ifndef都可以使用#else或#elif语句。
    #inlucde <stdio.h>
    #define T 10
    Int main(void)
    {
    #ifdef t
    Printf(“Hi T\n”);
    #else
    Printf(“Hi anyone\n”);
    #endif
    #ifndef M
    Printf(“M Not Defined\n”);
    #endif
    Return 0;
    }
    6.      #undef
    #undef指令删除前面定义的宏名字。也就是说,它“不定义”宏。一般形式为:
    #undef macro-name
    7.      使用defined
    除#ifdef之外,还有另外一种确定是否定义宏名字的方法,即可以将#if指令与defined编译时操作符一起使用。defined操作符的一般形式如下:
    defined macro-name
    如果macro-name是当前定义的,则表达式为真,否则为假。
    例如,确定宏MY是否定义,可以使用下列两种预处理命令之一:
    #if defined MY
    或
    #ifdef MY
    也可以在defined之前加上感叹号”!”来反转相应的条件。例如,只有在DEBUG未定义的情况下才编译。
    #if !defined DEBUG
    Printf(“Final Version!\n”);
    #endif
    使用defined的一个原因是,它允许由#elif语句确定的宏名字存在。
    8.      #line
    #line指令改变__LINE__和__FILE__的内容。__LINE__和__FILE__都是编译程序中预定义的标识符。标识符__LINE__的内容是当前被编译代码行的行号,__FILE__的内容是当前被编译源文件的文件名。#line的一般形式是:
    #line number “filename”
    其中,number是正整数并变成__LINE__的新值;可选的“filename”是合法文件标识符并变成__FILE__的新值。#line主要用于调试和特殊应用。
    
    9.      #pragma
    #pragma是编译程序实现时定义的指令,它允许由此向编译程序传入各种指令。例如,一个编译程序可能具有支持跟踪程序执行的选项,此时可以用#pragma语句选择该功能。编译程序忽略其不支持的#pragma选项。#pragma提高C源程序对编译程序的可移植性。
    10. 预处理操作符#和##
    有两个预处理操作符:#和##,它们可以在#define中使用。
    操作符#通常称为字符串化的操作符,它把其后的串变成用双引号包围的串。例如:
    #include <stdio.h>
    #define mkstr(s) #s
    int main(void)
    {
    Printf(mkstr(I like C));
    Return 0;
    }
    预处理程序把以下的语句:
    Printf(mkstr(I like C));
    变成
    Printf(“I like C”);
    操作符##把两个标记拼在一起,形成一个新标记。例如:
    #include <stdio.h>
    #define concat(a,a) a##b
    int main(void)
    {
    Int xy = 10;
    Printf(“%d”,concat(x,y));
    Return 0;
    }
    预处理程序把以下语句:
    Printf(“%d”,concat(x,y));
    变成
    Printf(“%d”,xy);
    操作符#和##主要作用是允许预处理程序对付某些特殊情况,多数程序中并不需要。
    11. 预定义宏
    C规范了5个固有的预定义宏,它们是:
    __LINE__
    __FILE__
    __DATE__
    __TIME__
    __STDC__
    __LINE__和__FILE__包含正在编译的程序的行号和文件名。
    __DATE__和内容形如month/day/year(月/日/年)的串,代表源文件翻译成目标码的日期。
    __TIME__中的串代表源代码编译成目标码的时间,形如hour:minute:second(时:分:秒)
    如果__STDC__的内容是十进制常数1,则表示编译程序的实现符合标准C。

     

    展开全文
  • 1、C语言预编译指令的作用是什么?有哪些预编译指令,作用分别是什么? 预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。可见预处理过程先于编译器对源代码进行处理。 在C语言中,并没有...

    参考http://blog.csdn.net/qq_21792169/article/details/50210713

    指针常量与常量指针

    下面代码的p有什么区别?

    代码1:int i=10;int * const p =&i;
    代码2:int i=10;const int * p=&i;
    答:

    代码1中 即指针常量。p是不可改变地址的指针,但是可以对它指向的内容进行修改。

    代码2中 即常量指针。p是指向常量的指针,p所指向的地址内容是不能修改的,但是p本身可以修改。


    指针运算

    ++(*p):先取指针指向的内容,然后+1,当前生效。++*p等价

    (*p)++:先取指针指向的内容,然后+1,加1在语句执行后生效。*p++等价

    *(p++):p指针加1,先取P当前内容,然后给P+1

    *(++p):p指针加1,先给p+1,然后取出内容

    int 指针变量+1,地址加4


    打印内存地址:

    printf("%p",&a):自带0x。

    printf("%p",&a):不带0x十六进制。


    字符与字符串

    char c=‘a’   char *cp=“a”

    (1)c是字符变量,用于代替单个字符,cp是字符指针变量,用于传递字符串

    (2)c替代字符常量‘a’  cp指向字符串常量

    (3)‘a’占一个字节,“a”占俩字节


    一维数组和指针

    char *p=“abcd”  char c[]=“abcd” 请问p++与c++是否相等?

    p++:p是字符类型指针变量,p本身在内存中占4个字节,p是指向字符串常量的指针。代表字符串首地址,然后P地址+1。

    c:c是数组名,也表示数组c的起始地址,该数组所占内存大小是字符串长度+1.\0 c是一个常量地址,c++是非法的。



    C语言预编译指令的作用是什么?有哪些预编译指令,作用分别是什么?

    预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。可见预处理过程先于编译器对源代码进行处理

    C语言中,并没有任何内在的机制来完成如下一些功能:在编译时包含其他源文件、定义宏、根据条件决定编译时是否包含某些代码。要完成这些工作,就需要使用预处理程序。尽管在目前绝大多数编译器都包含了预处理程序,但通常认为它们是独立于编译器的。预处理过程读入源代码,检查包含预处理指令的语句和宏定义,并对源代码进行响应的转换。预处理过程还会删除程序中的注释和多余的空白字符
    预处理指令是以#号开头的代码行。#号必须是该行除了任何空白字符外的第一个字符。#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。

    下面是部分预处理指令:

            指令             用途
             #           
    空指令,无任何效果
             #include    
    包含一个源代码文件
             #define     
    定义宏
             #undef      
    取消已定义的宏
             #if         
    如果给定条件为真,则编译下面代码
             #ifdef      
    如果宏已经定义,则编译下面代码
             #ifndef     
    如果宏没有定义,则编译下面代码

             #elif       
    如果前面的#if给定条件不为真,当前条件为真,则编译下面代码
             #endif      
    结束一个#if……#else条件编译块
             #error      
    停止编译并显示错误信息


    用预处理指令#define 声明一个常数,用以表明1年中有多少秒。

    答:   #define SECONDS_PER_YEAR  (60 * 60 * 24 * 365)UL

    考点:

    (1)#define 语法的基本知识(不能以分号结束,括号的使用)
    (2)预处理器将计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,这样更清晰明了。
    (3)这个表达式将使一个16位机的整型数溢出,因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
    (4)表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要,这说明考虑的很全面。


    写一个"标准"宏MIN ,这个宏输入两个参数并返回较小的一个。

    答:#define MIN(A,B) ((A) <= (B) ? (A) : (B)) 

    考点:
    (1)标识#define在宏中应用的基本知识。这是很重要的。因为在  嵌入(inline)操作符 变为标准C的一部分之前,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。
    (2)三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。
    (3)懂得在宏中把参数用括号括起来。

    (4) 我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?
            least = MIN(*p++, b);

    ((*p++) <= (b) ? (*p++) : (b)) 这个表达式会产生副作用,指针p会作两次++自增操作。


    预处理器标识#error的目的是什么?

    停止编译并显示错误信息。


    用变量a给出下面的定义

    a) 一个整型数(An integer) 
    b)一个指向整型数的指针( A pointer to an integer) 
    c)一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer toan intege)r 
    d)一个有10个整型数的数组( An array of 10integers) 
    e) 一个有10个指针的数组,该指针是指向一个整型数的。(Anarray of 10 pointers to integers) 
    f) 一个指向有10个整型数数组的指针( A pointerto an array of 10 integers) 
    g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a functionthat takes an integer as an argument and returns an integer) 
    h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argumentand return an integer )
    答案是: 

    a) int a; // An integer 
    b) int *a; // A pointer to an integer 
    c) int **a; // A pointer to a pointer to an integer 
    d) int a[10]; // An array of 10 integers 
    e) int *a[10]; // An array of 10 pointers to integers 
    f) int (*a)[10]; // A pointer to an array of 10 integers 
    g) int (*a)(int); // A pointer to a function a that takes an integer argumentand returns an integer 
    h) int (*a[10])(int); // An array of 10 pointers to functions that take aninteger argument and return an integer 


    关键字static的作用是什么?

    这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:
    1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
    2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
    3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。


    关键字const有什么含意?

    一个变量不允许被改变,产生静态作用。使用const在一定程度上可以提高程序的安全性和可靠性。const推出的初始目的,正是为了取代预编译指令,消除它的缺点,同时继承它的优点。const修饰的数据类型是指常类型,常类型的变量或对象的值是不能被更新的。合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。


    关键字volatile有什么含意?

    volatile是一个类型修饰符type specifier),就像大家更熟悉的const一样,它是被设计用来修饰被不同线程访问和修改的变量volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。

    volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。简单地说就是防止编译器对代码进行优化。比如如下程序:

    XBYTE[2]=0x55;
    XBYTE[2]=0x56;
    XBYTE[2]=0x57;
    XBYTE[2]=0x58;
    

    对外部硬件而言,上述四条语句分别表示不同的操作,会产生四种不同的动作,但是编译器却会对上述四条语句进行优化,认为只有XBYTE[2]=0x58(即忽略前三条语句,只产生一条机器代码)。如果键入volatile,则编译器会逐一的进行编译并产生相应的机器代码(产生四条代码)


    位操作

    嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。

    用 #defines 和 bit masks 操作。这是一个有极高可移植性的方法,是应该被用到的方法。最佳的解决方案如下:

    #define BIT3(0x1 << 3)
    static int a;
    
    voidset_bit3(void) 
    {
       a |= BIT3;
    }
    voidclear_bit3(void) 
    {
       a &= ~BIT3;
    }


    访问指定地址的内存

    嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。
    这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:

       int *ptr;
       ptr = (int *)0x67a9;
       *ptr = 0xaa55;

    一个较晦涩的方法是:

        *(int * const)(0x67a9) =0xaa55;
    建议你在面试时使用第一种方案。


    中断(Interrupts)

    中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。具代表事实是,产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。

    __interruptdouble compute_area (double radius) 
    {
       double area = PI * radius * radius;
       printf("/nArea = %f", area);
       return area;
    }

    这个函数有太多的错误了:
    1)ISR 不能返回一个值。如果你不懂这个,那么你不会被雇用的。
    2) ISR 不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。
    3) 在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。
    4) 与第三点一脉相承,printf()经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇用前景越来越光明了。

    __interrupt用来声明一个函数是中断处理函数;在严格的ANSIC/C++模式下,也可以使用interrupt关键字来代替。中断处理函数要遵循特殊的寄存器保存规则和退出顺序,从而保证代码的安全。在C/C++程序中产生中断时,所有被中断子程序使用,或者被中断子程序调用的函数使用的状态都需要被保留。此外,__interrupt定义的函数不能有参数,也没有返回值,即:

    __interrupt void int_handler()
    {
    unsigned int flags;
    ...
    }


    运算中的类型转换

    下面的代码输出是什么,为什么?

    void foo(void)
    {
        unsigned int a = 6;
        int b = -20;
        (a+b > 6) ? puts("> 6") : puts("<= 6");
    }
    

    这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是 ">6"。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。

     

    static关键字作用

    (1) static修饰的局部变量它的数值是上一次函数调用结束之后的数值,在修饰变量的时候,static修饰的静态局部变量只执行一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放。 

    (2)静态局部变量在定义的时候没有初始化,默认的初始值为0。

    (3)static修饰全局变量的时候,这个全局变量只能在本文件中访问,不能在其它文件中访问,即便是extern外部声明也不可以。
    (4)static修饰一个函数,则这个函数的只能在本文件中调用,不能被其他文件调用。Static修饰的局部变量存放在全局数据区的静态变量区。初始化的时候自动初始化为0; 
    #include <stdio.h>
    #include <stdlib.h>
    int RecordBuffer[10];  
    int buffer_write(unsigned int *buffer , int size_to_write) ;  
    void fun();  
    int main()  
    {  
      fun();  
      fun();  
        system("PAUSE");	
         return 0;   
    }  
    void fun()  
    {  
       static int a = 0;  
       a++ ;   
       printf("a:%d\n",a);  
    }  
    


    strlen与sizeof的区别

    strlen:是计算字符串的长度,当遇到‘\0’时停止,不包括‘\0’。

    sizeof:计算在内存中占得大小。要考虑字节对其等问题。32位系统,所有指针一般占4字节。

    char *a[3][4]占48个字节内存空间。

    数组作为参数时,数组名退化为指针变量。



    展开全文
  • C语言编程要点

    2017-09-18 00:10:37
    12.13. 适用于整数和浮点数的数学函数分别有哪些? 184 12.14. 什么是多字节字符(multibyte characters)? 185 12.15. 怎样操作由多字节字符组成的字符串? 186 第13章 时间和日期 186 13.1. 怎样把日期存储到单个数字...
  • c语言编写单片机技巧

    2009-04-19 12:15:17
    1. C语言和汇编语言在开发单片机时各有哪些优缺点? 答:汇编语言是一种用文字助记符来表示机器指令的符号语言,是最接近机器码的一种语言。其主要优点是占用资源少、程序执行效率高。但是不同的CPU,其汇编语言...
  • 你必须知道的495个C语言问题

    千次下载 热门讨论 2015-05-08 11:09:25
    *2.5 在C语言中是否模拟继承等面向对象程序设计特性的好方法? 2.6 为什么声明externf(structx*p);给我报了一个晦涩难懂的警告信息? 2.7 我遇到这样声明结构的代码:structname{intnamelen;charnamestr[1];}...
  • 第22课 - 条件编译使用分析 这节课我们介绍如何使用C语言中的条件编译。 市面上的电子产品一般低配版、中配版、高配版,... 条件编译是在预处理阶段由处理器完成的,处理器根据条件编译指令选择使用哪些代...

    第22课 - 条件编译使用分析

    这节课我们介绍如何使用C语言中的条件编译。

    市面上的电子产品一般有低配版、中配版、高配版,那相应的软件也要开发三个版本吗?显然不是这样的,我们一般在同一套代码中使用条件编译区分不同的版本。

    1. 基本概念

    (1)c 程序的编译一般经过如下四个过程

           

      条件编译是在预处理阶段由预处理器完成的,预处理器根据条件编译指令选择使用哪些代码。

    (2)条件编译的行为类似于if ...else...语句,但他们有本质的区别。前者在预处理阶段进行分支判断,后者在程序运行期间进行分支判断

     1 // #include <stdio.h>
     2 
     3 #define C 1
     4 
     5 int main()
     6 {
     7     const char* s;
     8 
     9     #if( C == 1 )   // 条件成立,选择该分支
    10         s = "This is first printf...\n";
    11     #else
    12         s = "This is second printf...\n";
    13     #endif
    14 
    15     // printf("%s", s);
    16     
    17     return 0;
    18 }

    使用 gcc -E 命令查看该程序由预处理器处理后的结果

    swj@ubuntu:~/c_course/ch_22$ gcc -E test.c
    # 1 "test.c"
    # 1 "<built-in>"
    # 1 "<command-line>"
    # 1 "/usr/include/stdc-predef.h" 1 3 4
    # 1 "<command-line>" 2
    # 1 "test.c"

    int main()
    {
    const char* s;

    s = "This is first printf...\n";

    return 0;
    }

    (3)除了在代码中定义宏,可以通过命令行定义宏       -D后面的宏会在预处理时传递到程序中(Ddefinition的缩写)

    gcc –Dmacro=value file.c    // 针对 #if 语句

    gcc –Dmacro file.c               // 针对 #ifdef 或 ifndef 语句

                                               // 查看gcc的man手册,这种形式下macro的值为1  

         

    下面验证-D选项的功能

     1 #include <stdio.h>
     2 
     3 int main()
     4 {
     5     const char* s;
     6 
     7     #if( C == 1 )
     8         s = "This is first printf...\n";
     9     #else
    10         s = "This is second printf...\n";
    11     #endif
    12 
    13     printf("%s", s);
    14     
    15     return 0;
    16 }

    上面代码删除了#define C 1,观察下面的编译命令及程序的输出结果

        

    这里如果直接 gcc test.c 程序也可以编译通过,在预处理 #if( C==1 ) 时,如果没有定义C,那么这里就为“假”(并没有报错)。

     2. #include的本质

     

    3. 条件编译的意义

     

    展开全文
  • 难道在C语言中一个结构不能包含指向自己的指针吗? o 2.7 怎样建立和理解非常复杂的声明?例如定义一个包含 N 个指向返回指向字符的指针的函数的指针的数组? o 2.8 函数只定义了一次, 调用了一次, 但编译器提示...
  • 《你必须知道的495个C语言问题》

    热门讨论 2010-03-20 16:41:18
    *2.5 在C语言中是否模拟继承等面向对象程序设计特性的好方法? 22 2.6 为什么声明extern f(struct x *p); 给我报了一个晦涩难懂的警告信息? 23 2.7 我遇到这样声明结构的代码:struct name {int namelen; ...
  • IvorHorton还著关于C、C++和Java的多部入门级好书,如《C语言入门经典(第4版)》和《C++入门经典(第3版)》。 译者  杨浩,知名译者,大学讲师,从事机械和计算机方面的教学和研究多年,发表论文数篇,参编和翻译的...
  • *2.5 在C语言中是否模拟继承等面向对象程序设计特性的好方法? 22 2.6 为什么声明extern f(struct x *p); 给我报了一个晦涩难懂的警告信息? 23 2.7 我遇到这样声明结构的代码:struct name {int namelen; ...
  • *2.5 在C语言中是否模拟继承等面向对象程序设计特性的好方法? 2.6 为什么声明externf(structx*p);给我报了一个晦涩难懂的警告信息?  2.7 我遇到这样声明结构的代码:structname{intnamelen;charnamestr[1];}...
  •  *2.5 在C语言中是否模拟继承等面向对象程序设计特性的好方法? 2.6 为什么声明externf(structx*p);给我报了一个晦涩难懂的警告信息? 2.7 我遇到这样声明结构的代码:structname{intnamelen;charnamestr[1];...
  • 你必须知道的495个C语言问题(PDF)

    热门讨论 2009-09-15 10:25:47
    难道在C语言中一个结构不能包含指向自己的指针吗? . . . . 3 1.7 怎样建立和理解非常复杂的声明?例如定义一个包含N 个指向返 回指向字符的指针的函数的指针的数组? . . . . . . . . . . . . . . 3 1.8 函数只定义...
  • 书中列出了C用户经常问的400多个经典问题,涵盖了初始化、数组、指针、字符串、内存分配、库函数、C处理器等各个方面的主题,并分别给出了解答,而且结合代码示例阐明要点。 本书结构清晰,讲解透彻,是各高校相关...
  • 书中列出了C用户经常问的400多个经典问题,涵盖了初始化、数组、指针、字符串、内存分配、库函数、C处理器等各个方面的主题,并分别给出了解答,而且结合代码示例阐明要点。  本书结构清晰,讲解透彻,是各高校...
  • C语言提供多种预处理功能,主要处理#开始的预编译指令,如宏定义(# define),文件包含(# include),条件编译(# ifdef)等(以*开头的都是预处理命令)。 2.条件语句和条件编译什么区别? 条件编译是C语言中预处理...
  • C语言提供多种预处理功能,主要处理#开始的预编译指令,如宏定义(# define),文件包含(# include),条件编译(# ifdef)等(以*开头的都是预处理命令)。2.条件语句和条件编译什么区别?条件编译是C语言中预处理部分...
  • 12.13 适用于整数和浮点数的数学函数分别有哪些? 12.14 什么是多字节字符(multibyte characters)? 12.15 怎样操作由多字节字符组成的字符串? 第13章 时间和日期 13.1 怎样把日期存储到单个数字中?有这...
  •  2.1.3 C++程序=预编译指令+程序代码+注释  2.1.4 编译器和链接器  2.1.5 C++程序的执行过程  2.1.6 程序的两大任务:描述?据与处理数据  2.2 基本输入/输出流  2.2.1 标准的输入和输出对象  2.2.2 输出格式...
  • 2.4.5 在多函数程序中使用using编译指令 2.5 总结 2.6 复习题 2.7 编程练习 第3章 处理数据 3.1 简单变量 3.1.1 变量名 3.1.2 整型 3.1.3 整型short、int、long和long long 3.1.4 无符号类型 3.1.5 选择...
  • 21天学通C++ (中文第五版)

    热门讨论 2010-06-23 16:57:03
    本书是针对C++初学者编写的,不要求读者有C语言方面的背景知识,可作为高等院校教授C++课程的教材,也可供初学者自学C++时使用。 译者介绍:Jesse Liberty 编著了大量有关软件开发的图书,其中包括C++和.NET方面的...
  • CruiseYoung提供的带详细书签的电子书籍目录 http://blog.csdn.net/fksec/article/details/7888251 Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐) 基本信息 原书名: Pro Oracle SQL 原出版社: ...
  • CruiseYoung提供的带详细书签的电子书籍目录 http://blog.csdn.net/fksec/article/details/7888251 该资料是《Oracle SQL高级编程》的源代码 对应的书籍资料见: Oracle SQL高级编程(资深Oracle专家力作,...

空空如也

空空如也

1 2
收藏数 30
精华内容 12
关键字:

c语言预编译指令有哪些

c语言 订阅