我正在编写一个C程序,其中我实现了一个函数来生成用于打印彩色文本的ANSI colored颜色 代码.

const char* getAnsiColorCode(int colorId) {
    static char colorCode[15];
    snprintf(colorCode, sizeof(colorCode), "\e[38;5;%dm", colorId);
    return colorCode;
}

我所需要做的就是打印一些彩色的问候世界:

int main(int argc, char *argv[]) {
    for (int i = 0; i < 256; i++) {
        printf("%sHello, World!\n", getAnsiColorCode(i));
    }
}

这是我能找到的最干净的解决方案,但我想知道,宣布colorCodestatic是不是一种糟糕的做法. 是否每次初始化colorCode都会覆盖相同的变量,或者前colorCode会留在内存中?我真的不喜欢他们都留在那里的 idea .但如果colorCode被覆盖,似乎也不是坏事.

我也try 了一些其他的解决方案,但我不太喜欢. 我不想在堆上分配colorCode,然后释放它. 我也不想把它作为一个论点来传递,因为这样看起来就不那么干净了. 还有比static更好的方法吗?static是不是一种糟糕的做法?

推荐答案

这种方法的问题是,您有一个隐藏的static状态,这使得您的函数既不是线程安全的,也不是同一表达式中的多个可调用的,包括间接的.

以下面的代码为例:

int main(int argc, char *argv[]) {
    for (int i = 0; i < 256; i++) {
        printf("%sHello, World!%s\n", getAnsiColorCode(i), getAnsiColorCode(0));
    }
}

输出将是不确定的,因为调用getAnsiColorCode的顺序是未指定的,但在所有情况下,printf输出的空间序列对于两个%s替换都是相同的.

可以返回静态字符串,只要它的值是恒定的,即:不会在调用之间改变.

有两种方法可以获得您的转义序列代码:

  • 在构造序列的位置使用足够长度的参数数组

    char *getAnsiColorCode(char colorCode[static 15], int colorId) {
        snprintf(colorCode, 15), "\e[38;5;%dm", colorId);
        return colorCode;
    }
    
    int main(int argc, char *argv[]) {
        for (int i = 0; i < 256; i++) {
            char colorCode[15];
            printf("%sHello, World!\n", getAnsiColorCode(colorCode, i));
        }
    }
    
  • 使用静态答案数组(不是完全线程安全的,但可以不受限制地多次调用):

    const char *getAnsiColorCode(int colorId) {
        static char colorCode[256][12];
        colorId %= 255;
        if (!*colorCode[colorId]) {
            snprintf(colorCode[colorId], sizeof colorCode[colorId],
                     "\e[38;5;%dm", colorId);
        }
        return colorCode[colorId];
    }
    
    int main(int argc, char *argv[]) {
        for (int i = 0; i < 256; i++) {
            printf("%sHello, World!\n", getAnsiColorCode(i));
        }
    }
    

C++相关问答推荐

Bison解析器转移/减少冲突

MISRA C:2012 11.3违规强制转换(FLOAT*)到(uint32_t*)

如何一次获取一个字符

正在try 将文件/文件夹名从目录 struct 存储到链接列表

难以理解Makefile隐含规则

C是否用0填充多维数组的其余部分?

LONG_DOUBLE_T是否存在(标准C:C23)

如何在不使用其他数组或字符串的情况下交换字符串中的两个单词?

如果dim指定数组中的数据量,使用dim-1会不会潜在地导致丢失一个元素?

SSH会话出现意外状态

C I/O:在Windows控制台上处理键盘输入

使用nmake for程序比Hello World稍微复杂一些

S,在 struct 中创建匿名静态缓冲区的最佳方式是什么?

不带Malloc的链表

CS50 pset 5的皱眉脸正确地处理了大多数基本单词,并且拼写判断不区分大小写.

计算SIZE_MAX元素的长数组的大小

区分MySQL C界面中的文本和BLOB字段

是什么阻止编译器优化手写的 memcmp()?

C11 嵌套泛型

C语言程序流程解释