智能车制作

 找回密码
 注册

扫一扫,访问微社区

查看: 1291|回复: 9
打印 上一主题 下一主题

[讨论] 关于#if

[复制链接]

48

主题

323

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2669
威望
1377
贡献
668
兑换币
240
注册时间
2012-3-31
在线时间
312 小时
跳转到指定楼层
1#
发表于 2013-3-5 21:39:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式





这两个有什么区别吗,第一个编译不过,第二个可以,是C中有这种说法还是IAR软件的规定啊《《

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

11

主题

211

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1260

优秀会员奖章活跃会员奖章

威望
690
贡献
318
兑换币
346
注册时间
2012-12-21
在线时间
126 小时
2#
发表于 2013-3-5 23:47:12 | 只看该作者
C语言预编译。
回复 支持 反对

使用道具 举报

4

主题

406

帖子

0

精华

跨届大侠

Rank: 10Rank: 10Rank: 10

积分
10980
威望
5409
贡献
3229
兑换币
2948
注册时间
2011-8-7
在线时间
1171 小时
3#
发表于 2013-3-6 10:29:04 | 只看该作者
没有#endif怎么确定#if的内容范围。。
回复 支持 反对

使用道具 举报

17

主题

280

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2298

优秀会员奖章活跃会员奖章

威望
1496
贡献
218
兑换币
575
注册时间
2012-9-26
在线时间
292 小时
4#
发表于 2013-3-6 12:15:27 | 只看该作者
C语言
回复 支持 反对

使用道具 举报

48

主题

323

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2669
威望
1377
贡献
668
兑换币
240
注册时间
2012-3-31
在线时间
312 小时
5#
 楼主| 发表于 2013-3-6 15:37:39 | 只看该作者
luomusic 发表于 2013-3-6 12:15
C语言

这种预编译和if...else的区别,是不是预编译是在程序执行前就已经处理完了
回复 支持 反对

使用道具 举报

0

主题

42

帖子

0

精华

高级会员

Rank: 4

积分
949
威望
495
贡献
268
兑换币
103
注册时间
2009-7-28
在线时间
93 小时
6#
发表于 2013-3-6 22:05:56 | 只看该作者
楼主首先要明白预编译的意义,我们可以通过以下两个程序来看预编译



而对于另一个不是以宏定义,而是以变量定义的程序:

运行的结果是:

我们可以看到,这两个程序的运行结果是一样的.但仅仅是结果一样而己.
接下来我们可以利用CPP命令来对程序进行展开,首先对precompile1.c展开,由于如果加入printf会引入库函数,因此我们将这两个函数的printf去掉再编译:

可以看到,在进行了预编译的程序中,实行上 a己经被2取代了,在程序的编译过程中,并没有所谓的a存在.
之后我们对其产生的编译后(但未链接,因为PC的链接过程中会产生别的信息,打印现来会一大堆,为了方便简单的讲解,我们使用编译后的可重定位文件进行讲解)进行信息的提取:
pubuntu@pubuntu:~/Desktop/precompile$ readelf -a precompile1.o
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          176 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           40 (bytes)
  Number of section headers:         9
  Section header string table index: 6

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000034 00000f 00  AX  0   0  4
  [ 2] .data             PROGBITS        00000000 000044 000000 00  WA  0   0  4
  [ 3] .bss              NOBITS          00000000 000044 000000 00  WA  0   0  4
  [ 4] .comment          PROGBITS        00000000 000044 000026 01  MS  0   0  1
  [ 5] .note.GNU-stack   PROGBITS        00000000 00006a 000000 00      0   0  1
  [ 6] .shstrtab         STRTAB          00000000 00006a 000045 00      0   0  1
  [ 7] .symtab           SYMTAB          00000000 000218 000080 10      8   7  4
  [ 8] .strtab           STRTAB          00000000 000298 000014 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no section groups in this file.

There are no program headers in this file.

There are no relocations in this file.

There are no unwind sections in this file.

Symbol table '.symtab' contains 8 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS precompile1.c
     2: 00000000     0 SECTION LOCAL  DEFAULT    1
     3: 00000000     0 SECTION LOCAL  DEFAULT    2
     4: 00000000     0 SECTION LOCAL  DEFAULT    3
     5: 00000000     0 SECTION LOCAL  DEFAULT    5
     6: 00000000     0 SECTION LOCAL  DEFAULT    4
     7: 00000000    15 FUNC    GLOBAL DEFAULT    1 main

No version information found in this file.
可以从里面看到,并没有出现这个叫a的东西的存在.
相同的,我们对precompile2.c进行cpp指令的展开

可以看到,函数代码中,是有a这个变量的,而不是像在预处理中被替换成了2.之后我们也同样可以对其产生的可重定位文件precompile2.o读取它的一些符号信息:
pubuntu@pubuntu:~/Desktop/precompile$ readelf -a precompile2.o
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          188 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           40 (bytes)
  Number of section headers:         10
  Section header string table index: 7

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000034 000012 00  AX  0   0  4
  [ 2] .rel.text         REL             00000000 0002f4 000008 08      8   1  4
  [ 3] .data             PROGBITS        00000000 000048 000004 00  WA  0   0  4
  [ 4] .bss              NOBITS          00000000 00004c 000000 00  WA  0   0  4
  [ 5] .comment          PROGBITS        00000000 00004c 000026 01  MS  0   0  1
  [ 6] .note.GNU-stack   PROGBITS        00000000 000072 000000 00      0   0  1
  [ 7] .shstrtab         STRTAB          00000000 000072 000049 00      0   0  1
  [ 8] .symtab           SYMTAB          00000000 00024c 000090 10      9   7  4
  [ 9] .strtab           STRTAB          00000000 0002dc 000016 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no section groups in this file.

There are no program headers in this file.

Relocation section '.rel.text' at offset 0x2f4 contains 1 entries:
Offset     Info    Type            Sym.Value  Sym. Name
00000007  00000701 R_386_32          00000000   a

There are no unwind sections in this file.

Symbol table '.symtab' contains 9 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS precompile2.c
     2: 00000000     0 SECTION LOCAL  DEFAULT    1
     3: 00000000     0 SECTION LOCAL  DEFAULT    3
     4: 00000000     0 SECTION LOCAL  DEFAULT    4
     5: 00000000     0 SECTION LOCAL  DEFAULT    6
     6: 00000000     0 SECTION LOCAL  DEFAULT    5
     7: 00000000     4 OBJECT  GLOBAL DEFAULT    3 a
     8: 00000000    18 FUNC    GLOBAL DEFAULT    1 main

No version information found in this file.
由此可以看出,这里出现了一个叫a的全局变量,它存在于数据段中,占了四个字节.
经过以上的两个程序的分析,就可以知道预编译实际是在程序没有进行编译之前,就对程序进行了处理.像楼主所提出的#if,以及#include都是这种情况.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

0

主题

42

帖子

0

精华

高级会员

Rank: 4

积分
949
威望
495
贡献
268
兑换币
103
注册时间
2009-7-28
在线时间
93 小时
7#
发表于 2013-3-6 22:08:40 | 只看该作者
接下来我们对#if做一个程序进行下分析:
#define a 5
void main()
{
        int x;       
        #if a==5
        x=5;
        #else
        x=10;
        #endif
}
我们使用CPP指令进行展开,会得到什么呢:

可以看到,x被直接赋值给了5.
接下来,我们对这个程序进行下改造:
int a=5;
void main()
{
        int x;       
        #if a==5
        x=5;
        #else
        x=10;
        #endif
}
我们使用变量来试图对程序进行影响,之后我们用cpp指令进行展开:

但是出现的结果是,x被赋值了10.这是为什么呢?
原因是预处理命令是在程序还没有编译之前的操作,此时程序并没有a这个东西,所以更不会出现所谓的比较,实际上程序在预处理的时候,是计算#if后的表达式的值,而此时表达式是:
a==5
由于a此时是不存在的,也就是undef的,所以undef ==5的值计算出来是0,所以说,就会走到#else分支.
由此,可以从这点来讲楼主的问题了:

#if后面的一整行都会作为一个表达式来求值.那么
(CARD) i=8;这个表达式的值是多少呢?
很可惜,这个表达式C编译器无法计算,所以自然也就通不过了.
但当你分开后

#if表达式是
(CARD)
如果
#define CARD 1
那么就会i=8;
如果
#define CARD 0
就会走 i=4;
如果啥也没写呢?
那就会走i=4
但如果你只写了一个 #define CARD呢?编译器会告诉你:
error: missing expression between '(' and ')'因为它也不知道CARD被定义成了什么东西.它只是知道它被定义了.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

48

主题

323

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2669
威望
1377
贡献
668
兑换币
240
注册时间
2012-3-31
在线时间
312 小时
8#
 楼主| 发表于 2013-3-6 22:10:10 | 只看该作者
受教了,谢谢!!
回复 支持 反对

使用道具 举报

48

主题

323

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2669
威望
1377
贡献
668
兑换币
240
注册时间
2012-3-31
在线时间
312 小时
9#
 楼主| 发表于 2013-3-6 22:10:24 | 只看该作者
ysjynkpgmw 发表于 2013-3-6 22:05
楼主首先要明白预编译的意义,我们可以通过以下两个程序来看预编译

受教了,谢谢!!
回复 支持 反对

使用道具 举报

48

主题

323

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2669
威望
1377
贡献
668
兑换币
240
注册时间
2012-3-31
在线时间
312 小时
10#
 楼主| 发表于 2013-3-6 22:15:47 | 只看该作者
ysjynkpgmw 发表于 2013-3-6 22:08
接下来我们对#if做一个程序进行下分析:
#define a 5
void main()

谢谢,,,,,
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

关于我们|联系我们|小黑屋|智能车制作 ( 黑ICP备2022002344号

GMT+8, 2024-11-6 03:38 , Processed in 0.054338 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表