Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 有没有一种方法可以实现头文件重命名时不必修改的头文件保护?_C_C Preprocessor_Header Files - Fatal编程技术网

C 有没有一种方法可以实现头文件重命名时不必修改的头文件保护?

C 有没有一种方法可以实现头文件重命名时不必修改的头文件保护?,c,c-preprocessor,header-files,C,C Preprocessor,Header Files,当前,对于名为test_header.h的头文件,我使用- 我想要的是一个不直接使用文件名的头保护。类似于一厢情愿的原始假设解决方案- 你可以随意命名头球后卫 如果标题与某个主题相关,请在该主题之后命名,即列出操作 忽略防护,然后编写一个脚本,根据当前文件名插入防护。编译前,将此脚本作为构建过程的一部分运行。记住在构建之后创建一个修改过的副本或删除include,否则您的头中会有很多include防护 根据您的项目应该使用的编译器,它们可能支持pragma-once方法。 它的可移植性非常好,受

当前,对于名为test_header.h的头文件,我使用-

我想要的是一个不直接使用文件名的头保护。类似于一厢情愿的原始假设解决方案-


你可以随意命名头球后卫

如果标题与某个主题相关,请在该主题之后命名,即列出操作 忽略防护,然后编写一个脚本,根据当前文件名插入防护。编译前,将此脚本作为构建过程的一部分运行。记住在构建之后创建一个修改过的副本或删除include,否则您的头中会有很多include防护 根据您的项目应该使用的编译器,它们可能支持pragma-once方法。 它的可移植性非常好,受到所有主要编译器以及14个编译器中的13个编译器的良好支持


也请注意。

正如其他人所指出的,你用什么作为头球护板本质上并不重要;它只需要在可能被共同包含的头集合中是唯一的

您可以创建UUID或GUID,并将其用作头保护或某种类型的哈希-MD5、SHA1、SHA2、SHA3等…。唯一的诀窍是处理一个前导数字的可能性;这很容易解决,我用H作为前缀

不过,大多数情况下,我使用基于文件名的名称,并且通常不经常重命名标题,因此这是一个问题

下面是一个名为hdrguard的脚本,我使用它为给定的头文件生成头保护线:

#!/bin/sh
#
# @(#)$Id: hdrguard.sh,v 1.8 2016/05/09 18:41:57 jleffler Exp $
#
# Generate #ifndef sequence to guard header against multiple inclusion

arg0=$(basename $0 .sh)

usestr="Usage: $arg0 [-bdfhimV] header.h [...]"

usage()
{
    echo "$usestr" 1>&2
    exit 1
}

help()
{
    echo "$usestr"
    echo
    echo "  -b  Use base name of file for guard"
    echo "  -d  Use _DOT_H after name (instead of _H)"
    echo "  -f  Use specified path name of file for guard (default)"
    echo "  -h  Print this help message and exit"
    echo "  -i  Omit _INCLUDED after name"
    echo "  -m  Generate MD5 hash value as header guard"
    echo "  -V  Print version information and exit"
    exit 0
}

opt_incl=yes
opt_base=no
opt_dot=no
opt_md5=no
while getopts bdfhimV opt
do
    case "$opt" in
    (b) opt_base=yes;;
    (d) opt_dot=yes;;
    (f) opt_base=no;;
    (h) help;;
    (i) opt_incl=no;;
    (m) opt_md5=yes;;
    (V) echo "$arg0: HDRGUARD Version "'$Revision: 1.8 $ ($Date: 2016/05/09 18:41:57 $)' | rcsmunger; exit 0;;
    (*) usage;;
    esac
done

shift $(($OPTIND - 1))

[ $# -eq 0 ] && usage

for i in "$@"
do
    if [ $opt_base = yes ]
    then i=$(basename $i)
    fi
    if [ $opt_dot = yes ]
    then i=$(echo "$i" | sed 's/\.h$/_dot_h/')
    fi
    i=$(echo $i | tr 'a-z' 'A-Z' | tr -s '/+.-' '____' | sed 's/^_//')
    if [ $opt_incl = yes ]
    then
        case "$i" in
        (*_INCLUDED)
            : OK;;
        (*)
            i="${i}_INCLUDED";;
        esac
    fi
    if [ $opt_md5 = yes ]
    then
        tmp=$(mktemp ./hdrgrd.XXXXXXXX)
        trap "rm -f $tmp; exit 1" 0 1 2 3 13 15 
        echo "$i.$(isodate compact)" > "$tmp"
        i=$(md5 "$tmp" | sed 'y/abcdef/ABCDEF/; s/\([^ ]*\) .*/H_\1/')
        rm -f "$tmp"
        trap 0 1 2 3 13 15
    fi
    echo
    echo "#ifndef $i"
    echo "#define $i"
    echo
    echo "#endif /* $i */"
    echo
done
它没有用于SHA1、SHA2或SHA3的代码-它可以选择以命令MD5的形式使用MD5。添加对替代哈希算法的支持并不困难。它不要求文件存在

示例使用:

$ hdrguard header.h

#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED

#endif /* HEADER_H_INCLUDED */

$ hdrguard -m header.h

#ifndef H_6DC5070597F88701EB6D2CCAACC73383
#define H_6DC5070597F88701EB6D2CCAACC73383

#endif /* H_6DC5070597F88701EB6D2CCAACC73383 */

$
我经常在vim中使用它,输入命令,如!!当光标位于空行上时,生成适合我正在编辑的标题的标题保护。这就是为什么它也会生成上下两行的空白线。

该命令使用脚本isodate和rcsmenger。使用参数compact,isodate命令等效于:

date +'%Y%m%d.%H%M%S'
complete命令支持多种替代格式,比在任何地方都必须键入date命令更简洁。您可以完全自由地放弃使用单独的脚本,只需将显示的扩展嵌入到hdrguard中。事实上,你可以只使用日期,这样就可以了;它只是散列操作的种子材料,以使被散列的数据唯一

$ isodate compact
20161228.185232
$
rcsmunger命令只是将RCS ID字符串转换为我更喜欢的格式来报告版本信息:

#!/usr/bin/env perl -p
#
# @(#)$Id: rcsmunger.pl,v 1.9 2015/11/02 23:54:32 jleffler Exp $
#
# Remove the keywords around the values of RCS keywords

use strict;
use warnings;

# Beware of RCS hacking at RCS keywords!
# Convert date field to ISO 8601 (ISO 9075) notation
s%\$(Date:) (\d\d\d\d)/(\d\d)/(\d\d) (\d\d:\d\d:\d\d) \$%\$$1 $2-$3-$4 $5 \$%go;
# Remove keywords
s/\$([A-Z][a-z]+|RCSfile): ([^\$]+) \$/$2/go;
例如:

$ hdrguard -V
hdrguard: HDRGUARD Version 1.8 (2016-05-09 18:41:57)
$

您可以将版本信息的打印视为旧式版本控制;如果您使用诸如git之类的DVCS,则必须进行不同的操作,这也是我没有为我的个人软件集大规模迁移到git的原因之一。

严格来说,重命名后,您不需要更改头保护-除非您有另一个文件接管旧名称。您可以使用带有前缀的标识符加上UUID,甚至更不用担心。许多编译器都支持使用pragma one…有pragma one包含保护转换器,反之亦然@bin,实际上有一些pragma是由标准C定义的-可移植性对于那些特定的pragma来说不是问题。但pragma once不在其中,我倾向于同意避免实现定义的行为的想法,例如使用非标准pragma产品。您的脚本还可以删除旧的include-guard,如果它们具有独特的格式,或者,如果右后卫已经在场,但使用pragma一次的程序并不严格符合要求,则什么也不做。如果您的目标是编写可移植代码,那么您将不会使用它,尽管支持它的主要编译器所占比例很大。
#!/usr/bin/env perl -p
#
# @(#)$Id: rcsmunger.pl,v 1.9 2015/11/02 23:54:32 jleffler Exp $
#
# Remove the keywords around the values of RCS keywords

use strict;
use warnings;

# Beware of RCS hacking at RCS keywords!
# Convert date field to ISO 8601 (ISO 9075) notation
s%\$(Date:) (\d\d\d\d)/(\d\d)/(\d\d) (\d\d:\d\d:\d\d) \$%\$$1 $2-$3-$4 $5 \$%go;
# Remove keywords
s/\$([A-Z][a-z]+|RCSfile): ([^\$]+) \$/$2/go;
$ hdrguard -V
hdrguard: HDRGUARD Version 1.8 (2016-05-09 18:41:57)
$