【问题标题】:Macros in system calls系统调用中的宏
【发布时间】:2013-06-12 19:08:27
【问题描述】:

在 c++ 中,在系统调用中使用宏是否可行且安全?以如下代码为例:

#define WINX 54
#define WINY 30

int main()
{
system("mode con lines=WINY cols=WINX");
...

在代码中可以安全使用吗?还是我必须手动构造一个字符串?

【问题讨论】:

    标签: c++ c macros system


    【解决方案1】:

    宏不会在字符串文字内展开。相反,您可以使用另一个宏将宏扩展为字符串文字,并使用字符串文字连接来创建所需的字符串:

    #define STR2(x) STR(x)
    #define STR(x) #x
    
    const char *cmd = "mode con lines=" STR2(WINY) " cols=" STR2(WINX);
    system(cmd);
    

    STR2 将提供的参数(例如WINY)扩展为定义的内容,然后将其传递给STRSTR 只是使用字符串化宏操作符,其结果是字符串文字。在代码被标记化并编译为目标代码之前,编译器会将相邻的字符串文字连接成单个字符串。

    如果宏比简单的数字更复杂,那么您需要手动构造一个字符串。在 C++ 中,最简单的方法是使用ostringstream(来自<sstream>):

    std::ostringstream oss;
    oss << "mode con lines=" << WINY << " cols=" << WINX;
    system(oss.str().c_str());
    

    【讨论】:

    • 值得一提的是,STR2(WINY) 扩展为字符串文字,并且在编译的早期阶段将相邻的字符串文字连接在一起。您可能还想提一下,宏不会在字符串文字中展开,这就是为什么这种方法是必要的。
    • 预处理器不应该在传递给系统之前构造字符串,所以我应该能够使用 system("mode con lines=" STR2(WINY) " cols=" STR2(WINX) ); ?
    • @user2403132:是的,但是你必须告诉预处理器来构造字符串;这就是"mode con lines=" STR2(WINY) " cols=" STR2(WINX) 所做的。 (您可以将其直接传递给system()cmd 声明并不是真正需要的。)
    • @user2403132:对 Keith 所说的话,是的。我把它分成一个单独的变量只是为了让它不那么混乱,但这不是必需的。
    【解决方案2】:

    宏当然不会在字符串中展开。所以,这个

    system("mode con lines=WINY cols=WINX");  
    

    不会扩展到

    system("mode con lines=30 cols=54");
    

    【讨论】:

      【解决方案3】:

      如果不需要WINX和WINY的实际十进制值,可以在执行时拼接静态字符串,节省资源:

      #define WINX "54"
      #define WINY "30"
      
      int main()
      {
      system("mode con lines=" WINY " cols=" WINX);
      

      【讨论】:

        【解决方案4】:

        你必须手动构造一个字符串。

        例如:

        char command[100];
        int result;
        sprintf(command, "mode con lines=%d cols=%d", WINY, WINX);
        result = system(command);
        

        不要忘记必需的包含指令:

        #include <stdio.h>
        #include <stdlib.h>
        

        请查阅您的系统文档以了解system 返回的值的含义。

        确保command 数组足够大以容纳完整的命令——或者,最好使用std::string 代替。 jxh's answer 展示了如何做到这一点。

        【讨论】:

        • 我想这对 OP 来说并不重要,但没有真正的理由在运行时这样做。
        • C++ 没有定义适用于std::stringsprintf 版本。
        • @jxh:我知道,我的意思是建议以其他方式构建std::stringjxh's answer 展示了如何做到这一点,并且比我的更好。
        猜你喜欢
        • 2014-12-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多