宏定义

(C++算法工程师考点总结)基础

房东的猫 提交于 2019-11-27 14:32:36
1、源程序是如何被编译成可执行的二进制程序的 预处理: 在程序编译之前,由预处理器对C++源程序完成预处理工作。预处理主要将源程序中的宏定义指令、条件编译指令、头文件包含指令以及特殊符号完成相应的替换工作。(该步骤不进行语法检查,这就是inline函数比宏定义安全的原因) 编译器: 以预编译的输出作为输入,利用C++运行库,通过词法分析和语法分析,在确认所有的指令都符合语法规则时,将其翻译成等价的中间代码表示或是汇编语言(.s 文本文件) 汇编器: 将以汇编语言的形式存在的程序转化为机器可识别的二进制代码(.o 二进制文件) 链接器: 经过汇编器之后的目标文件仍然是不可执行的,因为缺乏程序运行必须的动态链接库(.dll)和静态链接库(.lib),链接器就是将程序所引用的外部文件关联起来,形成 .exe 后缀的可执行文件。 2、动态链接库和静态链接库 静态链接库和动态链接库都是共享代码的方式。 静态链接库: 如果采用静态链接库,则无论你愿不愿意,lib中的指令都全部被直接包含在最终生成的EXE文件中。 静态链接库中不能包含其他的静态链接库或者动态链接库。 动态链接库: 若使用动态链接库,该DLL不必被包含在最终的EXE文件中,EXE文件执行时,可以“动态地”引用和卸载这个与EXE独立的DLL文件。 动态链接库中可以继续包含其他的静态链接库或者动态链接库。 3、C/C+

预编译

我与影子孤独终老i 提交于 2019-11-27 10:36:26
宏定义中的#运算符把跟在其后的参数转换成一个字符串称为字符串化运算符。 宏定义中的##运算符把出现在##两侧的参数合并成一个符号。 来源: https://www.cnblogs.com/mu-zhang/p/11359897.html

不同操作系统的宏定义区分

徘徊边缘 提交于 2019-11-27 10:01:43
转载自 不同操作系统的宏定义区分 #ifdef _WIN32 //define something for Windows (32-bit and 64-bit, this part is common) #ifdef _WIN64 //define something for Windows (64-bit only) #else //define something for Windows (32-bit only) #endif #elif __APPLE__ #include "TargetConditionals.h" #if TARGET_IPHONE_SIMULATOR // iOS Simulator #elif TARGET_OS_IPHONE // iOS device #elif TARGET_OS_MAC // Other kinds of Mac OS #else # error "Unknown Apple platform" #endif #elif __ANDROID__ // android #elif __linux__ // linux #elif __unix__ // all unices not caught above // Unix #elif defined(_POSIX_VERSION) // POSIX #else# error

u-boot

谁说胖子不能爱 提交于 2019-11-27 06:39:52
1.解压好u-boot后,打开uboot根目录的README文件,在software configuration 里有写明,如果要针对某个单板进行配置,需要执行:make <board_name>_config 其中uboot支持的board_name可以在根目录的include/configs/下查看。 2.makefile 2.1 uboot version确定 (Makefile 24-29行) U_BOOT_VERSION “1.3.4xyz” 1)uboot版本号分为4个级别: VERSION : 主板号 PATCHLEVEL : 次版本号 SUBLEVEL : 再次版本号 EXTRAVERSION : 另外附加的版本信息 这4个用 . 分隔开共同构成了最终的版本号。 2)makefile中版本号最终生成一个变量U_BOOT_VERSION,这个变量记录了Makefile中配置的版本号。 Include/version_autogenerated.h文件是编译过程中自动生成的一个文件,所有源目录中没有,但是编译过后的uboot中就有了。它里面的内容是一个宏定义,宏定义的值就是我们在Makefile中配置的uboot版本号。 3)验证方法:自己修改主makefile中几个version有关的变量,然后编译uboot,然后烧录到SD卡中,从SD卡中启动

C 语言宏定义

泪湿孤枕 提交于 2019-11-27 01:31:39
C 语言宏定义 1、例子如下: #define PRINT_STR(s) printf("%s",s.c_str()) string str = "abcd"; PRINT_STR(str); 结果如下:abcd 2、现在我期望打印出,str=abcd, 容易想到的解决办法是: #define PRINT_STR(s) printf("s" "=" "%s",s.c_str()) 打印出来的结果是 s=abcd,不是我们所期望的,想一下,为什么? 在这里,编译器不认为"s"中s就是前面的s,不进行替换。如果进行替换,那么"%s" 也就换成了"%str",这显然错误。 3、怎么解决上面的问题?使用另一种方式,也就是#(字符串替换,前后加上双引号),如下: #define PRINT_STR(s) printf(#s "=" "%s",s.c_str()) 可以认为,对于#s,编译器对s进行替换,并且在s前后加上双引号 4、考虑下面的情况, int token8 = 102; PRINT_TOKEN(8); 期望打印出 token8,容易想到的解决办法是: #define PRINT_TOKEN(d) printf("%d",tokend) 这样是明显错误的,编译器认为tokend是一个整体,不可能只去替换d,怎么解决? 5、怎么解决这个问题?要进行替换,必须把d隔离出来

inline,宏定义,static,extern

六月ゝ 毕业季﹏ 提交于 2019-11-26 21:49:56
inline一般用于定义代码简洁,耗时短,不像宏定义是在预编译阶段替换,inline是在汇编阶段替换,效果一样。 一般编译器进行优化的时候会对简短方法进行这种优化,不进行声明也会进行inline,如果显示的声明为inline,会增大最后代码的大小。最终是否优化由编译器决定,这样声明了可以在头文件中定义,不用担心重复定义。 static是告诉链接器,当前文件定义的方法和变量只有当前模块可用,不能被其他的模块使用。 注意,对于 include 方式进行包含的没有影响。 include 实际是对整个文件进行包含。这个一般是对于库与库,或者 .o 与 .o 之间,可见范围由编译器进行分隔。 extern是告诉编译器,如果当前项目没有定义相关的变量, 不需要报错,在链接阶段一定会有相关的定义的。 和static 有些类似,也是使用于模块与模块之间的。 宏定义是在预编译阶段就进行替换。 可以通过 g++ -E source.cpp 的方式查看替换后的代码。 /* [root@localhost definecompile]# g++ -E test.cpp # 1 "test.cpp" # 1 "<built-in>" # 1 "<命令行>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 1 "<命令行>" 2 # 1 "test.cpp" */ int

inline,宏定义,static,extern

ⅰ亾dé卋堺 提交于 2019-11-26 21:29:25
inline一般用于定义代码简洁,耗时短,不像宏定义是在预编译阶段替换,inline是在汇编阶段替换,效果一样。 一般编译器进行优化的时候会对简短方法进行这种优化,不进行声明也会进行inline,如果显示的声明为inline,会增大最后代码的大小。最终是否优化由编译器决定,这样声明了可以在头文件中定义,不用担心重复定义。 static是告诉链接器,当前文件定义的方法和变量只有当前模块可用,不能被其他的模块使用。 注意,对于 include 方式进行包含的没有影响。 include 实际是对整个文件进行包含。这个一般是对于库与库,或者 .o 与 .o 之间,可见范围由编译器进行分隔。 extern是告诉编译器,如果当前项目没有定义相关的变量, 不需要报错,在链接阶段一定会有相关的定义的。 和static 有些类似,也是使用于模块与模块之间的。 宏定义是在预编译阶段就进行替换。 可以通过 g++ -E source.cpp 的方式查看替换后的代码。 /* [root@localhost definecompile]# g++ -E test.cpp # 1 "test.cpp" # 1 "<built-in>" # 1 "<命令行>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 1 "<命令行>" 2 # 1 "test.cpp" */ int

C语言宏定义中L##"STRING"

瘦欲@ 提交于 2019-11-25 20:43:43
在USB字符串描述符中 bLength为描述符长度,bDeorType为描述符类型,字符编码统一采用UNICODE编码,UNICODE采用两个字节字节表示一个字符,如果是英语字符的话,那就很简单了,直接在ASCII码前面补上一个为0x00的字节数据就组成UNICODE编码了。 但是在C编译器中, #define WIDE_STRING(string) _WIDE_STRING(string) #define _WIDE_STRING(string) L##string 通过WIDE_STRING(“string”)配合wchar可以将“string”直接变成UNICODE。 #define WIDE_STRING(string) _WIDE_STRING(string) #define _WIDE_STRING(string) L##string #define USBD_STRING_DESC(string) (uint8_t *)&(struct { uint8_t _len; uint8_t _type; wchar_t _data[sizeof(string)]; }) { sizeof(WIDE_STRING(string)) + 2U - 2U, USB_DESCTYPE_STRING, WIDE_STRING(string) } L"string