网站上的按钮怎么做,如何用网站模板建站,洞头区小程序模板源代码,做网站公司 晨旭东方Halo#xff0c;这里是Ppeua。平时主要更新C语言#xff0c;C#xff0c;数据结构算法......感兴趣就关注我吧#xff01;你定不会失望。 #x1f308;个人主页#xff1a;主页链接 #x1f308;算法专栏#xff1a;专栏链接 我会一直往里填充内容哒#xff01; … 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都是预处理指令。
#includestdio.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 printfPLTmovl $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否则未定义 #includestdio.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定义中不要加
来看看这段代码当条件成立时amax否则bmax
#define MAX 5;
if trueaMAX;
elsebMAX;
但是在预编译处理阶段会将这段代码翻译成这样也就将else孤立了会导致语法错误
#define MAX 5;
if trueaMAX;
elsebMAX;
所以在define中不需要加入
3.2.1#define 定义宏 #define 机制包括了一个规定允许把参数替换到文本中这种实现通常称为宏macro或定义宏define macro。 下面是宏的申明方式
#define name( parament-list ) stuff 其中的 parament-list 是一个由逗号隔开的符号表它们可能出现在stuff中。
#define max(x,y) ((xy)?x:y)
参数列表的左括号必须与name紧邻。 如果两者中有空白的部分则会被解释为stuff。
写宏时不要吝啬括号否则会出现不好的结果
例如定义平方和的宏
#define SQUARE( x ) x * x
int a 5;
printf(%d\n ,SQUARE( a 1) )
在预编译结束后这段代码会变成什么呢
#define SQUARE( a1 ) a1 * a1
int a 5;
printf(%d\n ,a1 * a1 )
这时显然结果改变了所以我们应当这样定义宏
#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 #和##
#的作用是将变量名插入到字符串中
#includestdio.h
#define PRINTF(format,x) printf(the value of #x is format \n,x)
int main()
{int a4;PRINTF(%d, a);
}
这段代码预处理完为
int main()
{int a4;printf(the value of a is %d \n,a);
}##的作用是拼接两个常量
#includestdio.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 的编译器提供了一种能力允许在命令行中定义符号。用于启动编译过程。 例如当我们根据同一个源文件要编译出一个程序的不同版本的时候这个特性有点用处。假定某个程序中声明了一个某个长度的数组如果机器内存有限我们需要一个很小的数组但是另外一个机器内存大些我们需要一个数组能够大些。
#includestdio.h
int main()
{int array[MAX_SIZE];int i0;for(int i0;iMAX_SIZE;i)scanf(%d,array[i]);for(int i0;iMAX_SIZE;i)printf(%d,array[i]);return 0;
}
在gcc下输入 gcc -D MAX_SIZE10 test.c
这时MAX_SIZE的值就为10 3.5 文件包含
我们已经知道 #include 指令可以使另外一个文件被编译。就像它实际出现于 #include 指令的地方一样。 这种替换的方式很简单 预处理器先删除这条指令并用包含文件的内容替换。 这样一个源文件被包含10次那就实际被编译10次。 所以我们在写头文件的时候一般会加上
#ifndef _TEST_H__ //头文件名 或者自己创建一个标识符
#define _TEST_H__
//头文件内容
#endif 这里的代码也很好理解判断是否有这个定义若没有则进入下面的内容若有则结束解决了头文件被重复包含的问题当然也可以这样写。
#pragma oncce 完结撒花 本篇博客的内容【程序环境和预处理】已经结束。 若对你有些许帮助可以点赞、关注、评论支持下博主你的支持将是我前进路上最大的动力。 若以上内容有任何问题欢迎在评论区指出。若对以上内容有任何不解都可私信评论询问。 诸君山顶见