【C语言技能树】程序环境和预处理
Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法......感兴趣就关注我吧!你定不会失望。
🌈个人主页:主页链接
🌈算法专栏:专栏链接
我会一直往里填充内容哒!
🌈LeetCode专栏:专栏链接
目前在刷初级算法的LeetBook 。若每日一题当中有力所能及的题目,也会当天做完发出
🌈代码仓库:Gitee链接
🌈点击关注=收获更多优质内容🌈
目录
1. 程序的翻译环境和执行环境:
2. 详解编译+链接
2.1翻译环境
2.2 编译本身也分为几个阶段 预编译,编译与处理.
2.21预编译
2.22编译
2.23汇编阶段
2.3链接
3. 预处理详解
3.1 预定义符号
3.2 #define
3.2.1#define 定义宏
3.2.2 #define 替换规则
3.2.3 #和##
3.2.4 宏和函数对比
3.2.7 命名约定
3.3 #undef
3.4 命令行定义
3.5 文件包含
完结撒花:
1. 程序的翻译环境和执行环境:
在ANSI C的任何一种实现中,存在两个不同的环境。
第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。
第2种是执行环境,它用于实际执行代码
在计算机当中,只能执行二进制编码,那我们的编程语言又是如何转换成二进制编码的呢?
以我们常用的vs为例,这是一个集成开发环境,从.c到.exe都可以由他来完成.
经过编译与链接这两个大步骤,就可以生成可执行程序.
2. 详解编译+链接
2.1翻译环境
组成一个程序的每个源文件通过编译过程分别转换成目标代码(object code)。
每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序。
链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中
2.2 编译本身也分为几个阶段 预编译,编译与处理.
2.21预编译
预处理阶段会将预处理指令进行替换
如下的#include 与 #define都是预处理指令。
#include<stdio.h>
#define MAX 5
int main()
{printf("%d",MAX);return 0;
//预处理
}
使用gcc执行:gcc -E test.c -o test.i 可在预处理后停下.这时预处理指令替换完成
define定义的常量进行文本替换 include所包含的头文件被展开,注释将被删除
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "test.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 1 3 4
# 33 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 461 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4
# 452 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 453 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/long-double.h" 1 3 4
# 454 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 462 "/usr/include/features.h" 2 3 4
# 485 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4
# 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4
# 486 "/usr/include/features.h" 2 3 4
# 34 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 2 3 4
# 28 "/usr/include/stdio.h" 2 3 4# 1 "/usr/lib/gcc/x86_64-linux-gnu/9/include/stddef.h" 1 3 4
# 209 "/usr/lib/gcc/x86_64-linux-gnu/9/include/stddef.h" 3 4# 209 "/usr/lib/gcc/x86_64-linux-gnu/9/include/stddef.h" 3 4
typedef long unsigned int size_t;
# 34 "/usr/include/stdio.h" 2 3 4# 1 "/usr/lib/gcc/x86_64-linux-gnu/9/include/stdarg.h" 1 3 4
# 40 "/usr/lib/gcc/x86_64-linux-gnu/9/include/stdarg.h" 3 4
typedef __builtin_va_list __gnuc_va_list;
# 37 "/usr/include/stdio.h" 2 3 4# 1 "/usr/include/x86_64-linux-gnu/bits/types.h" 1 3 4
# 27 "/usr/include/x86_64-linux-gnu/bits/types.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 28 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/timesize.h" 1 3 4
# 29 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
typedef unsigned long int __u_long;typedef signed char __int8_t;
typedef unsigned char __uint8_t;
typedef signed short int __int16_t;
typedef unsigned short int __uint16_t;
typedef signed int __int32_t;
typedef unsigned int __uint32_t;typedef signed long int __int64_t;
typedef unsigned long int __uint64_t;typedef __int8_t __int_least8_t;
typedef __uint8_t __uint_least8_t;
typedef __int16_t __int_least16_t;
typedef __uint16_t __uint_least16_t;
typedef __int32_t __int_least32_t;
typedef __uint32_t __uint_least32_t;
typedef __int64_t __int_least64_t;
typedef __uint64_t __uint_least64_t;typedef long int __quad_t;
typedef unsigned long int __u_quad_t;typedef long int __intmax_t;
typedef unsigned long int __uintmax_t;
# 141 "/usr/include/x86_64-linux-gnu/bits/types.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/typesizes.h" 1 3 4
# 142 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/time64.h" 1 3 4
# 143 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4typedef unsigned long int __dev_t;
typedef unsigned int __uid_t;
typedef unsigned int __gid_t;
typedef unsigned long int __ino_t;
typedef unsigned long int __ino64_t;
typedef unsigned int __mode_t;
typedef unsigned long int __nlink_t;
typedef long int __off_t;
typedef long int __off64_t;
typedef int __pid_t;
typedef struct { int __val[2]; } __fsid_t;
typedef long int __clock_t;
typedef unsigned long int __rlim_t;
typedef unsigned long int __rlim64_t;
typedef unsigned int __id_t;
typedef long int __time_t;
typedef unsigned int __useconds_t;
typedef long int __suseconds_t;typedef int __daddr_t;
typedef int __key_t;typedef int __clockid_t;typedef void * __timer_t;typedef long int __blksize_t;typedef long int __blkcnt_t;
typedef long int __blkcnt64_t;typedef unsigned long int __fsblkcnt_t;
typedef unsigned long int __fsblkcnt64_t;typedef unsigned long int __fsfilcnt_t;
typedef unsigned long int __fsfilcnt64_t;typedef long int __fsword_t;typedef long int __ssize_t;typedef long int __syscall_slong_t;typedef unsigned long int __syscall_ulong_t;typedef __off64_t __loff_t;
typedef char *__caddr_t;typedef long int __intptr_t;typedef unsigned int __socklen_t;typedef int __sig_atomic_t;
# 39 "/usr/include/stdio.h" 2 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/types/__fpos_t.h" 1 3 4# 1 "/usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h" 1 3 4
# 13 "/usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h" 3 4
typedef struct
{int __count;union{unsigned int __wch;char __wchb[4];} __value;
} __mbstate_t;
# 6 "/usr/include/x86_64-linux-gnu/bits/types/__fpos_t.h" 2 3 4typedef struct _G_fpos_t
{__off_t __pos;__mbstate_t __state;
} __fpos_t;
# 40 "/usr/include/stdio.h" 2 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h" 1 3 4
# 10 "/usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h" 3 4
typedef struct _G_fpos64_t
{__off64_t __pos;__mbstate_t __state;
} __fpos64_t;
# 41 "/usr/include/stdio.h" 2 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/types/__FILE.h" 1 3 4struct _IO_FILE;
typedef struct _IO_FILE __FILE;
# 42 "/usr/include/stdio.h" 2 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/types/FILE.h" 1 3 4struct _IO_FILE;typedef struct _IO_FILE FILE;
# 43 "/usr/include/stdio.h" 2 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h" 1 3 4
# 35 "/usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h" 3 4
struct _IO_FILE;
struct _IO_marker;
struct _IO_codecvt;
struct _IO_wide_data;typedef void _IO_lock_t;struct _IO_FILE
{int _flags;char *_IO_read_ptr;char *_IO_read_end;char *_IO_read_base;char *_IO_write_base;char *_IO_write_ptr;char *_IO_write_end;char *_IO_buf_base;char *_IO_buf_end;char *_IO_save_base;char *_IO_backup_base;char *_IO_save_end;struct _IO_marker *_markers;struct _IO_FILE *_chain;int _fileno;int _flags2;__off_t _old_offset;unsigned short _cur_column;signed char _vtable_offset;char _shortbuf[1];_IO_lock_t *_lock;__off64_t _offset;struct _IO_codecvt *_codecvt;struct _IO_wide_data *_wide_data;struct _IO_FILE *_freeres_list;void *_freeres_buf;size_t __pad5;int _mode;char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
};
# 44 "/usr/include/stdio.h" 2 3 4
# 52 "/usr/include/stdio.h" 3 4
typedef __gnuc_va_list va_list;
# 63 "/usr/include/stdio.h" 3 4
typedef __off_t off_t;
# 77 "/usr/include/stdio.h" 3 4
typedef __ssize_t ssize_t;typedef __fpos_t fpos_t;
# 133 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/stdio_lim.h" 1 3 4
# 134 "/usr/include/stdio.h" 2 3 4extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;extern int remove (const char *__filename) __attribute__ ((__nothrow__ , __leaf__));extern int rename (const char *__old, const char *__new) __attribute__ ((__nothrow__ , __leaf__));extern int renameat (int __oldfd, const char *__old, int __newfd,const char *__new) __attribute__ ((__nothrow__ , __leaf__));
# 173 "/usr/include/stdio.h" 3 4
extern FILE *tmpfile (void) ;
# 187 "/usr/include/stdio.h" 3 4
extern char *tmpnam (char *__s) __attribute__ ((__nothrow__ , __leaf__)) ;extern char *tmpnam_r (char *__s) __attribute__ ((__nothrow__ , __leaf__)) ;
# 204 "/usr/include/stdio.h" 3 4
extern char *tempnam (const char *__dir, const char *__pfx)__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ;extern int fclose (FILE *__stream);extern int fflush (FILE *__stream);
# 227 "/usr/include/stdio.h" 3 4
extern int fflush_unlocked (FILE *__stream);
# 246 "/usr/include/stdio.h" 3 4
extern FILE *fopen (const char *__restrict __filename,const char *__restrict __modes) ;extern FILE *freopen (const char *__restrict __filename,const char *__restrict __modes,FILE *__restrict __stream) ;
# 279 "/usr/include/stdio.h" 3 4
extern FILE *fdopen (int __fd, const char *__modes) __attribute__ ((__nothrow__ , __leaf__)) ;
# 292 "/usr/include/stdio.h" 3 4
extern FILE *fmemopen (void *__s, size_t __len, const char *__modes)__attribute__ ((__nothrow__ , __leaf__)) ;extern FILE *open_memstream (char **__bufloc, size_t *__sizeloc) __attribute__ ((__nothrow__ , __leaf__)) ;extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) __attribute__ ((__nothrow__ , __leaf__));extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf,int __modes, size_t __n) __attribute__ ((__nothrow__ , __leaf__));extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf,size_t __size) __attribute__ ((__nothrow__ , __leaf__));extern void setlinebuf (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));extern int fprintf (FILE *__restrict __stream,const char *__restrict __format, ...);extern int printf (const char *__restrict __format, ...);extern int sprintf (char *__restrict __s,const char *__restrict __format, ...) __attribute__ ((__nothrow__));extern int vfprintf (FILE *__restrict __s, const char *__restrict __format,__gnuc_va_list __arg);extern int vprintf (const char *__restrict __format, __gnuc_va_list __arg);extern int vsprintf (char *__restrict __s, const char *__restrict __format,__gnuc_va_list __arg) __attribute__ ((__nothrow__));extern int snprintf (char *__restrict __s, size_t __maxlen,const char *__restrict __format, ...)__attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 4)));extern int vsnprintf (char *__restrict __s, size_t __maxlen,const char *__restrict __format, __gnuc_va_list __arg)__attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 0)));
# 379 "/usr/include/stdio.h" 3 4
extern int vdprintf (int __fd, const char *__restrict __fmt,__gnuc_va_list __arg)__attribute__ ((__format__ (__printf__, 2, 0)));
extern int dprintf (int __fd, const char *__restrict __fmt, ...)__attribute__ ((__format__ (__printf__, 2, 3)));extern int fscanf (FILE *__restrict __stream,const char *__restrict __format, ...) ;extern int scanf (const char *__restrict __format, ...) ;extern int sscanf (const char *__restrict __s,const char *__restrict __format, ...) __attribute__ ((__nothrow__ , __leaf__));extern int fscanf (FILE *__restrict __stream, const char *__restrict __format, ...) __asm__ ("" "__isoc99_fscanf");
extern int scanf (const char *__restrict __format, ...) __asm__ ("" "__isoc99_scanf");
extern int sscanf (const char *__restrict __s, const char *__restrict __format, ...) __asm__ ("" "__isoc99_sscanf") __attribute__ ((__nothrow__ , __leaf__));
# 432 "/usr/include/stdio.h" 3 4
extern int vfscanf (FILE *__restrict __s, const char *__restrict __format,__gnuc_va_list __arg)__attribute__ ((__format__ (__scanf__, 2, 0))) ;extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg)__attribute__ ((__format__ (__scanf__, 1, 0))) ;extern int vsscanf (const char *__restrict __s,const char *__restrict __format, __gnuc_va_list __arg)__attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__format__ (__scanf__, 2, 0)));extern int vfscanf (FILE *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vfscanf")__attribute__ ((__format__ (__scanf__, 2, 0))) ;
extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vscanf")__attribute__ ((__format__ (__scanf__, 1, 0))) ;
extern int vsscanf (const char *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vsscanf") __attribute__ ((__nothrow__ , __leaf__))__attribute__ ((__format__ (__scanf__, 2, 0)));
# 485 "/usr/include/stdio.h" 3 4
extern int fgetc (FILE *__stream);
extern int getc (FILE *__stream);extern int getchar (void);extern int getc_unlocked (FILE *__stream);
extern int getchar_unlocked (void);
# 510 "/usr/include/stdio.h" 3 4
extern int fgetc_unlocked (FILE *__stream);
# 521 "/usr/include/stdio.h" 3 4
extern int fputc (int __c, FILE *__stream);
extern int putc (int __c, FILE *__stream);extern int putchar (int __c);
# 537 "/usr/include/stdio.h" 3 4
extern int fputc_unlocked (int __c, FILE *__stream);extern int putc_unlocked (int __c, FILE *__stream);
extern int putchar_unlocked (int __c);extern int getw (FILE *__stream);extern int putw (int __w, FILE *__stream);extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream);
# 603 "/usr/include/stdio.h" 3 4
extern __ssize_t __getdelim (char **__restrict __lineptr,size_t *__restrict __n, int __delimiter,FILE *__restrict __stream) ;
extern __ssize_t getdelim (char **__restrict __lineptr,size_t *__restrict __n, int __delimiter,FILE *__restrict __stream) ;extern __ssize_t getline (char **__restrict __lineptr,size_t *__restrict __n,FILE *__restrict __stream) ;extern int fputs (const char *__restrict __s, FILE *__restrict __stream);extern int puts (const char *__s);extern int ungetc (int __c, FILE *__stream);extern size_t fread (void *__restrict __ptr, size_t __size,size_t __n, FILE *__restrict __stream) ;extern size_t fwrite (const void *__restrict __ptr, size_t __size,size_t __n, FILE *__restrict __s);
# 673 "/usr/include/stdio.h" 3 4
extern size_t fread_unlocked (void *__restrict __ptr, size_t __size,size_t __n, FILE *__restrict __stream) ;
extern size_t fwrite_unlocked (const void *__restrict __ptr, size_t __size,size_t __n, FILE *__restrict __stream);extern int fseek (FILE *__stream, long int __off, int __whence);extern long int ftell (FILE *__stream) ;extern void rewind (FILE *__stream);
# 707 "/usr/include/stdio.h" 3 4
extern int fseeko (FILE *__stream, __off_t __off, int __whence);extern __off_t ftello (FILE *__stream) ;
# 731 "/usr/include/stdio.h" 3 4
extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos);extern int fsetpos (FILE *__stream, const fpos_t *__pos);
# 757 "/usr/include/stdio.h" 3 4
extern void clearerr (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));extern int feof (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;extern int ferror (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;extern void clearerr_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
extern int feof_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
extern int ferror_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;extern void perror (const char *__s);# 1 "/usr/include/x86_64-linux-gnu/bits/sys_errlist.h" 1 3 4
# 26 "/usr/include/x86_64-linux-gnu/bits/sys_errlist.h" 3 4
extern int sys_nerr;
extern const char *const sys_errlist[];
# 782 "/usr/include/stdio.h" 2 3 4extern int fileno (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;extern int fileno_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
# 800 "/usr/include/stdio.h" 3 4
extern FILE *popen (const char *__command, const char *__modes) ;extern int pclose (FILE *__stream);extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__));
# 840 "/usr/include/stdio.h" 3 4
extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
# 858 "/usr/include/stdio.h" 3 4
extern int __uflow (FILE *);
extern int __overflow (FILE *, int);
# 873 "/usr/include/stdio.h" 3 4# 2 "test.c" 2# 3 "test.c"
int main()
{printf("%d",5);return 0;
}
2.22编译
在编译阶段会将c代码全部翻译为汇编代码 并进行 词法分析 语义分析 语法分析 符号汇总等工作
同样在gcc中执行:gcc -S test.i -o test.s
.file "test.c".text.section .rodata
.LC0:.string "%d".text.globl main.type main, @function
main:
.LFB0:.cfi_startprocendbr64pushq %rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq %rsp, %rbp.cfi_def_cfa_register 6movl $5, %esileaq .LC0(%rip), %rdimovl $0, %eaxcall printf@PLTmovl $0, %eaxpopq %rbp.cfi_def_cfa 7, 8ret.cfi_endproc
.LFE0:.size main, .-main.ident "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0".section .note.GNU-stack,"",@progbits.section .note.gnu.property,"a".align 8.long 1f - 0f.long 4f - 1f.long 5
0:.string "GNU"
1:.align 8.long 0xc0000002.long 3f - 2f
2:.long 0x3
3:.align 8
4:
刚刚的代码就被翻译成了汇编代码。并完成了上述过程。
其中符号汇总将使用到的各个函数与全局变量汇总
2.23汇编阶段
在编译中最后的阶段是汇编,将文件生成为目标文件,将汇编代码翻译成二进制代码,并整合刚刚的符号汇总生成符号表,并附上地址,以便之后调用。
同样在gcc中执行:gcc -C test.s -o test.o
就生成了这样一个乱码文件(可使用elf格式进行编辑)
2.3链接
最后就是链接阶段,合并段表,并执行符号表的合并与重定位。
当多文件操作的时候,这部会将多个文件进行链接操作。(也可以理解为将多个文件合并为一个文件)
在gcc中执行 gcc test.o -o test
就会生成一个可执行程序。
3. 预处理详解
3.1 预定义符号
__FILE__
//进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译的日期
__TIME__ //文件被编译的时间
__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义
#include<stdio.h>
#define MAX 5
int main()
{printf(__FILE__);printf(__FUNCTION__);printf(__TIME__);
}
执行结果如下。分别为文件名 函数名 时间
3.2 #define
#define name stuff
语法为要定义的名字 与 具体的值
如
#define MAX 5
如果定义的 stuff过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)。
#define DEBUG_PRINT printf("file:%s\tline:%d\t \
date:%s\ttime:%s\n" ,\
__FILE__,__LINE__ ,\
__DATE__,__TIME__ )
在define定义中不要加;
来看看这段代码,当条件成立时a=max否则b=max
#define MAX 5;
if truea=MAX;
elseb=MAX;
但是在预编译处理阶段会将这段代码翻译成这样,也就将else孤立了,会导致语法错误
#define MAX 5;
if truea=MAX;;
elseb=MAX;;
所以在define中不需要加入;
3.2.1#define 定义宏
#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)。
下面是宏的申明方式:
#define name( parament-list ) stuff
其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中。
#define max(x,y) ((x>y)?x:y)
参数列表的左括号必须与name紧邻。 如果两者中有空白的部分,则会被解释为stuff。
写宏时不要吝啬括号,否则会出现不好的结果
例如:定义平方和的宏
#define SQUARE( x ) x * x
int a = 5;
printf("%d\n" ,SQUARE( a + 1) );
在预编译结束后这段代码会变成什么呢?
#define SQUARE( a+1 ) a+1 * a+1
int a = 5;
printf("%d\n" ,a+1 * a+1 );
这时,显然结果改变了,所以我们应当这样定义宏
#define SQUARE( x ) ((x) * (x))
int a = 5;
printf("%d\n" ,SQUARE( a + 1) );
3.2.2 #define 替换规则
在程序中扩展#define定义符号和宏时,需要涉及几个步骤。
1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先
被替换。
2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上
述处理过程。
注意:
1. 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。
2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。
3.2.3 #和##
#的作用是将变量名插入到字符串中
#include<stdio.h>
#define PRINTF(format,x) printf("the value of " #x " is " format "\n",x)
int main()
{int a=4;PRINTF("%d", a);
}
这段代码预处理完为
int main()
{int a=4;printf("the value of " "a" " is " "%d" "\n",a);
}
##的作用是拼接两个常量
#include<stdio.h>
#define ADD_TO_SUM(num,value) value##num
int main()
{printf("%f",ADD_TO_SUM(2.12, 2023));
}
代码结果为
3.2.4 宏和函数对比
属性 | #define定义宏 | 函数 |
代码长度 | 每次使用时,宏代码都会被插入到程序中。除了非常 小的宏之外,程序的长度会大幅度增长 | 函数代码只出现于一个地方;每次使用这个函数时,都调用那个地方的同一份代码 |
执行速度 | 更快 | 存在函数的调用和返回的额外开销,所以相对慢一些 |
操作优先级 | 需要根据上下文判断 | 表达式求值更容易预测 |
调试 | 不可调式 | 可以逐语句调试 |
递归 | 宏不可以递归 | 可以递归 |
3.2.7 命名约定
把宏名全部大写
函数名不要全部大写
3.3 #undef
这条指令用于移除一个宏定义。
#undef NAME
3.4 命令行定义
许多C 的编译器提供了一种能力,允许在命令行中定义符号。用于启动编译过程。
例如:当我们根据同一个源文件要编译出一个程序的不同版本的时候,这个特性有点用处。(假定某个程序中声明了一个某个长度的数组,如果机器内存有限,我们需要一个很小的数组,但是另外一个机器内存大些,我们需要一个数组能够大些。)
#include<stdio.h>
int main()
{int array[MAX_SIZE];int i=0;for(int i=0;i<MAX_SIZE;i++)scanf("%d",&array[i]);for(int i=0;i<MAX_SIZE;i++)printf("%d",array[i]);return 0;
}
在gcc下输入 gcc -D MAX_SIZE=10 test.c
这时MAX_SIZE的值就为10
3.5 文件包含
我们已经知道, #include 指令可以使另外一个文件被编译。就像它实际出现于 #include 指令的地方一样。
这种替换的方式很简单:
预处理器先删除这条指令,并用包含文件的内容替换。
这样一个源文件被包含10次,那就实际被编译10次。
所以我们在写头文件的时候一般会加上
#ifndef _TEST_H__ //头文件名 (或者自己创建一个标识符)
#define _TEST_H__
//头文件内容
#endif
这里的代码也很好理解,判断是否有这个定义,若没有则进入下面的内容,若有则结束,解决了头文件被重复包含的问题,当然也可以这样写。
#pragma oncce
完结撒花:
🌈本篇博客的内容【程序环境和预处理】已经结束。
🌈若对你有些许帮助,可以点赞、关注、评论支持下博主,你的支持将是我前进路上最大的动力。
🌈若以上内容有任何问题,欢迎在评论区指出。若对以上内容有任何不解,都可私信评论询问。
🌈诸君,山顶见!
相关文章:
【C语言技能树】程序环境和预处理
Halo,这里是Ppeua。平时主要更新C语言,C,数据结构算法......感兴趣就关注我吧!你定不会失望。 🌈个人主页:主页链接 🌈算法专栏:专栏链接 我会一直往里填充内容哒! &…...
数据库的三大范式
1.为什么需要数据库设计 设计数据表的时候,要考虑很多的问题: 用户需要哪些数据,我们在数据表中要保存哪一些数据怎么保证数据表中的数据的正确性如何降低数据表的冗余度开发人员怎么才能更方便的使用数据库 如果数据库设计得不合理的话,可…...
【MT7628】开发环境搭建-Fedora12安装之后无法上网问题解决
1.按照如下图所示,打开Network Connections 2.点击Network Connections,弹出如下界面...
[Android Studio]Android 数据存储-文件存储学习笔记-结合保存QQ账户与密码存储到指定文件中的演练
🟧🟨🟩🟦🟪 Android Debug🟧🟨🟩🟦🟪 Topic 发布安卓学习过程中遇到问题解决过程,希望我的解决方案可以对小伙伴们有帮助。 📋笔记目…...
【openGauss实战9】深度分析分区表
📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】!😜&am…...
XSS跨站脚本攻击剖析与防御:初识XSS
目录 跨站脚本介绍 1. 什么是XSS跨站脚本 2. XSS跨站脚本实例 3. XSS漏洞的危害 XSS的分类 1. 反射型XSS 2. 持久性XSS XSS构造 1. 利用< >标记注射Html /Javascript 2. 利用HTML标签属性值执行XSS 3. 空格回车Tab 4. 对标签属性值转码 5. 产生自己的事件…...
Python 高级编程之网络编程 Socket(六)
文章目录一、概述二、Python socket 模块1)Socket 类型1、创建 TCP Socket2、创建 UDP Socket2)Socket 函数1、服务端socket函数2、客户端socket函数3、公共socket函数三、单工,半双工以及全双工通信方式的区别四、单工,半双工以及…...
centos学习记录
遇到的问题及其解决办法 centos7安装图形化界面 yum groupinstall ‘X Window System’ yum groupinstall -y ‘GNOME Desktop’ 安装完成后输入init 5进入图形化界面 centos7安装vmware-tools 第一步卸载open-vm-tools 输入命令 yum remove open-vm-tools 输入命令 reboot 在…...
为什么说网络安全是风口行业?
前言 “没有网络安全就没有国家安全”。当前,网络安全已被提升到国家战略的高度,成为影响国家安全、社会稳定至关重要的因素之一。 网络安全行业特点 1、就业薪资非常高,涨薪快 2021年猎聘网发布网络安全行业就业薪资行业最高人均33.77万&…...
12-PHP使用过的函数 111-120
111、rowCount if ($stmt->execute($data)) {//true//读:select//写:insert,update,delete,成功后会返回表中受影响的记录数量//!rowCount() 返回受影响的记录数量if ($stmt->rowCount() > 0) {echo 新增成功,id . $db->lastInsertId() . <hr>;} else {//…...
【JavaWeb项目】简单搭建一个前端的博客系统
博客系统项目 本项目主要分成四个页面: 博客列表页博客详情页登录页面博客编辑页 该系统公共的CSS样式 common.css /* 放置一些各个页面都会用到的公共样式 */* {margin: 0;padding: 0;box-sizing: 0; }/* 给整个页面加上背景 */ html, body{height: 100%; }body {backgrou…...
iPerf3 -M参数详解,场景分析
本文目录iPerf3 -M参数说明几个典型测试场景中应该如何设定合适的-M参数值理想局域网模型(无丢包,无抖动)高丢包,无抖动模型高丢包,高抖动模型(网络质量比较差,IP转发路径变化频繁)总…...
java的基本语法以及注意事项
Java 基础语法一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作。下面简要介绍下类、对象、方法和实例变量的概念。对象:对象是类的一个实例,有状态和行为。例如,一条狗是一个对象,它…...
matlab搭建IAE,ISE,ITAE性能指标
目录前言准备IAEISEITAE前言 最近在使用matlab搭建控制系统性能评价指标模型,记录一下 准备 MATLAB R2020 IAE IAE函数表达式如下所示: IAE函数模型如下所示: ISE ISE函数表达式如下所示: ISE函数模型如下所示ÿ…...
docker安装mysql
在安装Mysql之前,我们可以先查看一下我们的镜像,输入命令: docker images 能发现,镜像里面只有一个Nginx,并没有Mysql 然后我们可以像上一篇安装Nginx一样,安装Mysql镜像。 输入以下命令,安装…...
Leetcode 回溯详解
回溯法 回溯法有“通用解题法”之称,用它可以系统地搜索问题的所有解。回溯法是一个既带有系统性又带有跳跃性的搜索算法。 在包含问题的所有解的解空间树中,按照深度优先搜索(DFS))的策略,从根结点出发深度探索解空间树。当探索…...
AI_Papers:第一期
2023.02.06—2023.02.12 文摘词云 Top Papers Subjects: cs.CL 1.Multimodal Chain-of-Thought Reasoning in Language Models 标题:语言模型中的多模式思维链推理 作者:Zhuosheng Zhang, Aston Zhang, Mu Li, Hai Zhao, George Karypis, Alex Sm…...
C/C++内存管理
C/C内存管理C/C内存分布C语言中内存管理的方式:malloc/calloc/realloc/freeC内存管理方式内置类型自定义类型operator new 与operator deletenew和delete的实现原理内置类型自定义类型定位new表达式(placement-new)new/delete与malloc/free的区别C/C内存分布 我们先…...
【大数据hive】hive 函数使用详解
一、前言 在任何一种编程语言中,函数可以说是必不可少的,像mysql、oracle中,提供了很多内置函数,或者通过自定义函数的方式进行定制化使用,而hive作为一门数据分析软件,随着版本的不断更新迭代,…...
彻底搞懂分布式系统服务注册与发现原理
目录 引入服务注册与发现组件的原因 单体架构 应用与数据分离...
安卓Camera2用ImageReader获取NV21源码分析
以前如何得到Camera预览流回调 可以通过如下方法,得到一路预览回调流 Camera#setPreviewCallbackWithBuffer(Camera.PreviewCallback),可以通过如下方法,设置回调数据的格式,比如 ImageFormat.NV21 Camera.Parameters#setPreview…...
24. 两两交换链表中的节点
文章目录题目描述迭代法递归法参考文献题目描述 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 示例 1: 输入&a…...
linux006之帮助命令
linux帮助命令简介: linux的命令是非常多的,光靠人是记不住的,在工作中一般都会去网上查,这是有外网的情况下,如果项目中不允许访问外网,那么linux的帮助命令就可以派上用场了, linux帮助命令是…...
【C++初阶】十三、模板进阶(总)|非类型模板参数|模板的特化|模板分离编译|模板总结(优缺点)
目录 一、非类型模板参数 二、模板的特化 2.1 模板特化概念 2.2 函数模板特化 2.3 类模板特化 2.3.1 全特化 2.3.2 偏特化 三、模板分离编译 四、模板总结(优缺点) 前言:之前模板初阶并没有把 C模板讲完,因为当时没有接触…...
Linux之文本搜索命令
文本搜索命令学习目标能够知道文本搜索使用的命令1. grep命令的使用命令说明grep文本搜索grep命令效果图:2. grep命令选项的使用命令选项说明-i忽略大小写-n显示匹配行号-v显示不包含匹配文本的所有行-i命令选项效果图:-n命令选项效果图:-v命令选项效果图:3. grep命令结合正则表…...
微信小程序Springboot 校园拼车自助服务系统java
系统管理员: 管理员账户管理:在线对管理员的账户信息进行管理,包括对管理员信息的增加修改以及密码的修改等。 站内新闻管理:在后台对站内新闻信息进行发布,并能够对站内新闻信息进行删除修改等。 论坛版块管理&#x…...
【Unity3D 常用插件】Haste插件
一,Haste介绍 Haste插件是一款针对 Unity 3D 的 Everthing软件,可以实现基于名称快速定位对象的功能。Unity 3D 编辑器也自带了搜索功能,但是在 project视图 和 Hierarchy视图 中的对象需要分别查找,不支持模糊匹配。Haste插件就…...
【c++面试问答】全局变量和局部变量的区别
问题 C中的全局变量和局部变量有什么区别? 注:内容全部参考自文末的参考资料 全局变量和局部变量的区别 可以从以下4个角度来区分: 区别全局变量局部变量作用域全局作用域局部作用域内存分配全局变量在静态数据区静态局部变量在静态数据区…...
Java List集合
6 List集合 List系列集合:添加的元素是有序,可重复,有索引 ArrayList: 添加的元素是有序,可重复,有索引LinkedList: 添加的元素是有序,可重复,有索引Vector :是线程安全的ÿ…...
linux服务器挂载硬盘/磁盘
1. 查看机器所挂硬盘个数及分区情况:fdisk -l可以看出来目前/dev/vda 目前有300G可用.内部有两个分区(/dev/vda1,/dev/vda2)。2. 格式化磁盘格式化磁盘命令为【mkfs.磁盘类型格式 目录路径组成】查看磁盘文件格式:df -T格式化磁盘…...
常州网站建设公司方案/网站推广方式
使用 .NET4 中的Task优化线程池【.NET4 多核并行】 阅读本篇前,读者需对.NET4 System.Threading.Tasks 以及 Task Schedulers 有一定的了解。如果不是很了解,请查阅以下相关信息: Task: http://msdn.microsoft.com/en-us/library/system.thre…...
自己怎么做网站啊/无人区在线观看高清1080
Linux系统平台下用Fdisk分区格式化硬盘 格式化与分区 hd--IDE设备 sd--SCSI设备 fdisk -l /dev/sda 查看第一块硬盘分区情况 fdisk /dev/sdb 给第二块硬盘分区 command acton (m for help):m #显示命令列表 a-设置可引导标志;b-设置卷标; d-删…...
美女教师做爰网站/多地优化完善疫情防控措施
引言 前面Android开发之旅:环境搭建及HelloWorld,我们介绍了如何搭建Android开发环境及简单地建立一个HelloWorld项目,本篇将通过HelloWorld项目来介绍Android项目的目录结构。本文的主要主题如下: 1、HelloWorld项目的目录结构 1…...
目标网站上做关键字布局/最新经济新闻
正则表达式 正则表达式是指一个用来描述或者匹配一系列符合某个语法规则的字符串的单个字符串。其实就是一种规则。有自己特殊的应用。正则表达式的表达类: 字符类: [abc] a、b 或 c(简单类)[ ^abc ] 任何字符,除了 a…...
寿光专业做网站的公司/域名注册服务网站哪个好
由于 WordPress大部分的主题都是使用Google的在线字体方案:Google Fonts. Google服务不稳定,导致大量独立博客字体加载不出来,直接导致博客打开速度变慢,严重时甚至导致网站打不开. 解决方案1: 编辑 WordPress 中的文…...
汽车城网站建设方案/下载百度 安装
转载于:https://blog.51cto.com/1101837/2087926...