C语言文件名、行号、函数名的方法

一、前言

在后台程序运行出问题时,需要查看详尽的日志,C语言提供记录日志触发点文件名、行号、函数名的方法,关键是利用C99新增的预处理标识符__VA_ARGS__;先介绍几个编译器内置的宏定义,这些宏定义不仅可以帮助我们完成跨平台的源码编写,灵活使用也可以巧妙地帮我们输出非常有用的调试信息。

二、ANSI C标准宏

__LINE__    // 在源代码中插入当前源代码行号
__FILE__    // 在源文件中插入当前源文件名
__DATE__    // 在源文件中插入当前的编译日期
__TIME__    // 在源文件中插入当前编译时间
__STDC__    // 当要求程序严格遵循ANSI C标准时该标识被赋值为1
__cplusplus // 当编写C++程序时该标识符被定义

_WIN32      // 在程序运行在windows系统上被定义位1
linux       // 在程序运行在linux系统上被定义位1
__x86_64__  // 在程序运行在64位系统上被定义位1
__i386__    // 在程序运行在32位系统上被定义位1

__VA_ARGS__ // 是一个可变参数的宏,这个可宏是新的C99规范中新增的,
            // 目前似乎gcc和VC6.0之后的都支持(VC6.0的编译器不支持)。
            // 宏前面加上##的作用在于,可以接受参数为0个或者多个

三、实例

宏实例:

#include <stdio.h>

int main()
{
    printf("__func__:%s\n", __func__);
    printf("__FILE__:%s\n", __FILE__);
    printf("__DATE__:%s\n", __DATE__);
    printf("__TIME__:%s\n", __TIME__);
    printf("__LINE__:%d\n", __LINE__);

    return 0;
}

宏实例程序输出如下:

__func__:main
__FILE__:main.c
__DATE__:Sep 14 2019
__TIME__:14:26:36
__LINE__:9

四、#和##运算符

其中#和##运算符的功能有所不同,在这里也做一定的介绍

1. #用来把参数转换成字符串

实例1:

#define P(A) printf("%s:%d\n",#A,A);
int main()
{
    int a = 1, b = 2;
    P(a);
    P(b);
    P(a+b);

    return 0;
}

实例1程序输出如下:

a:1
b:2
a+b:3

实例2:

#define SQUARE(x) printf("The square of "#x" is %d.\n", ((x)*(x)))
int main()
{
    SQUARE(8);

    return 0;
}

实例2程序输出如下:

The square of 8 is 64

2. ##运算符可以用于宏函数的替换部分

#define XNAME(n) x ## n

// 如果这样使用宏:XNAME(8)
// 则会被展开成这样:x8

##就是个粘合剂,将前后两部分粘合起来,也就是有“字符化”的意思。但是“##”不能随意粘合任意字符,必须是合法的C语言标示符。在单一的宏定义中,最多可以出现一次“#”或“##”预处理操作符。如果没有指定与“#”或“##”预处理操作符相关的计算次序,则会产生问题。为避免该问题,在单一的宏定义中只能使用其中一种操作符(即,一份“#”或一个“##”,或都不用)。除非非常有必要,否则尽量不要使用“#”和“##”。

__VA_ARGS__ 是一个可变参数的宏,很少人知道这个宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有gcc支持(VC6.0的编译器不支持)。实现思想就是宏定义中参数列表的最后一个参数为省略号(也就是三个点)。

##__VA_ARGS__ 宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的","去掉的作用,否则会编译出错;##__VA_ARGS__的实例:

#define my_print1(fmt,...) printf(fmt, __VA_ARGS__)
my_print1("iiijjj\n")        // 错误打印
my_print1("i=%d,j=%d\n",i,j) // 正确打印

#define my_print2(fmt,...) printf(fmt, ##__VA_ARGS__)
my_print2("iiijjj\n")        // 正确打印
my_print2("i=%d,j=%d\n",i,j) // 正确打印

原文地址:https://www.cnblogs.com/macrored/p/11519145.html

时间: 2024-10-09 19:36:23

C语言文件名、行号、函数名的方法的相关文章

C/C++ 打印源文件名和行号函数名的宏

__FILE__             宏在预编译时会替换成当前的源文件名__LINE__             宏在预编译时会替换成当前的行号 __FUNCTION__   宏在预编译时会替换成当前的函数名称

C/C++ 打印文件名、行号、函数名的方法

转自:http://blog.csdn.net/cabinriver/article/details/8960119 今天跟踪一段开源代码的时候,因为对代码不太熟悉,所以要打印一些关键的信息.便顺手整理了一下这个能打印文件名.行号.函数名的宏. 1.打印文件名.行号.函数的两种方式 [cpp] view plain copy /************************************************************************** *  @Copyri

显示行号的6种方法、chkconfig、tar、awk、cut过滤字符串、ps配合wc查看过滤进程

Day10 Georgekai-习惯:操作前备份,操作后检查 第1章 第二波剩余命令:显示行号的6种方法.chkconfig.tar.awk.cut过滤字符串.ps配合wc查看过滤进程 1.1 打印配置文件nginx.conf内容的行号及内容,该如何做? 1.1.1 花括号的作用 {} 注:生成序列,连续输入显示到屏幕,包括数字和字母 例1:[[email protected] ~]$ echo {1..10} 1 2 3 4 5 6 7 8 9 10 例二:[[email protected]

python 动态获取当前运行的类名和函数名的方法

一.使用内置方法和修饰器方法获取类名.函数名 python中获取函数名的情况分为内部.外部,从外部的情况好获取,使用指向函数的对象,然后用__name__属性 复制代码代码如下: def a():passa.__name__ 除此之外还可以: 复制代码代码如下: getattr(a,'__name__') 尽管有些脱裤子放屁,总之,从外部获取的方法是非常灵活的. 有些同学需要从函数内部获取函数本身的名字,就需要用些技巧了.1.使用sys模块的方法: 复制代码代码如下: def a():print

DataGridView显示行号的几种方法来自http://www.soaspx.com/dotnet/csharp/csharp_20100204_2740.html

方法一: 网上最常见的做法是用DataGridView的RowPostPaint事件在RowHeaderCell中绘制行号: private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)        {            try            {                //添加行号                 SolidBrush v_SolidBr

linux查看文件行号的七种方法

文件内容如下,要求显示文件内容对应的行号 [[email protected] ~ 13:01:16]# cat 123.txt  name:i am gaoyang birthday:19961025 what the fuck!!!! 1.cat -n 123.txt [[email protected] ~ 13:54:38]# cat -n 123.txt       1 name:i am gaoyang      2      3 birthday:19961025      4  

C++ 打印文件名, 行号,编译日期和时间例子

/*********************************************************************************    Copyright (C), 1988-1999, drvivermonkey. Co., Ltd.    File name:     Author: Driver Monkey    Version:     Mail:[email protected]    Date: 2014.04.02    Description

python中打印文件名,行号,路径

print "I have a proble! And here is at Line: %s"%sys._getframe().f_lineno PDB,哈哈http://docs.python.org/library/pdb.html import fileinput fileinput.filename() import srcinfo print ('warning: %s: %d: %s' %(srcinfo.file(), srcinfo.line(), x)) 绝对路径

python获得类名和函数名的方法

#!/usr/bin/python3 import sys class Point: def __init__( self, x=0, y=0): self.x = x self.y = y def __del__(self): class_name = self.__class__.__name__ fun_name = sys._getframe().f_code.co_name print (fun_name,class_name, "destroyed") p = Point(