如何避免使用全局变量?

时间:2016-06-06 07:59:41

标签: c global-variables lemon

使用全局变量是否可以?我正在使用全局变量,我知道这并不理想。看起来像这样

int result2 = 0;

void setresult2(int a) {
    result2 = a;
}

我在我的自定义shell中使用我的柠檬语法中的变量:

expr(A) ::= IF LSBR expr(B) RSBR SEMICOLON THEN expr(C) SEMICOLON FI. { setresult2(B); A=C; }

现在我想知道是否有比使用全局变量更好的方法?

整个代码可在my github上找到。全局变量的目的是在shell扩展和shell脚本中处理if语句,以便我的shell可以读取并执行if语句。

上下文中的代码是使用更新全局变量的语法的if语句的解析,这是在语法和我的C之间进行通信的唯一方式:

char *if_execute(char *shellcommand) {

    char mystring[CMD_LEN];
    void *pParser;
    char *c;
    int reti;
    shellcommand = str_replace(shellcommand, ";", " ; ");
    reti = regcomp(&regex, "[0-9]==[0-9]", 0);
    if (reti) {
        fprintf(stderr, "Could not compile regex\n");
        exit(1);
    }

    /* Execute regular expression */
    reti = regexec(&regex, shellcommand, 0, NULL, 0);
    if (!reti) {
        shellcommand = str_replace(shellcommand, "==", " == ");;
    }
    else if (reti == REG_NOMATCH) {
        /* puts("No match"); */
    }
    else {
        regerror(reti, &regex, msgbuf, sizeof(msgbuf));
        fprintf(stderr, "Regex match failed: %s\n", msgbuf);
        exit(1);
    }

    char *line = strcpy(mystring, shellcommand);
    pParser = (void *) ParseAlloc(malloc);
    if (line) {
        char *buf[64];
        struct SToken v[32];
        int value;
        char **ptr1 = str_split(buf, line, ' ');
        int j = 0;
        for (j = 0; ptr1[j]; j++) {
            c = ptr1[j];
            char *c2 = strdup(c);
            if (c2 == NULL) {
                perror("strdup");
                exit(EXIT_FAILURE);
            }
            v[j].token = c2;
            switch (*c2) {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                    for (value = 0; *c2 && *c2 >= '0' && *c2 <= '9'; c2++)
                        value = value * 10 + (*c2 - '0');
                    v[j].value = value;
                    Parse(pParser, INTEGER, &v[j]);
                    continue;
            }

            if (!strcmp("if", c)) {
                Parse(pParser, IF, NULL);
            }
            else if (!strcmp("true", c)) {
                Parse(pParser, TRUE, NULL);
            }
            else if (!strcmp("then", c)) {
                Parse(pParser, THEN, NULL);
                char *token = "then ";
                const char *p1 = strstr(shellcommand, token) + strlen(token);
                const char *p2 = strstr(p1, ";");
                if (p2 == NULL) {
                    // TODO: Handle it
                }
                size_t len = p2 - p1;
                char *res = (char *) malloc(sizeof(char) * (len + 1));
                if (res == NULL) {
                    fprintf(stderr, "malloc failed!\n");
                }
                strncpy(res, p1, len);
                res[len] = '\0';

                if (result2)
                    shellcommand = res;
                else
                    shellcommand = "echo";
            }
            else if (!strcmp("[", c)) {
                Parse(pParser, LSBR, NULL);
            }
            else if (!strcmp("]", c)) {
                Parse(pParser, RSBR, NULL);
            }
            else if (!strcmp(";", c)) {
                Parse(pParser, SEMICOLON, NULL);
            }
            else if (!strcmp("fi", c)) {
                Parse(pParser, FI, NULL);
            }
            else if (strlen(c) > 0 && strstr(c, "==")) {
                v[j].token = c;
                Parse(pParser, EQEQ, &v[j]);
            }
            else {
                Parse(pParser, FILENAME, NULL);
            }
        }
        Parse(pParser, 0, NULL);
    }

    return shellcommand;
}

2 个答案:

答案 0 :(得分:1)

我不是专家,但通常答案是直截了当的。 如果你不想使用全局变量(这通常是一个好主意),那么你需要传递局部变量作为你想要使用它的函数的引用并更新调用函数 (通常在main())。

答案 1 :(得分:1)

我会说“成员变量”在代码的非通用部分可以正常。例如。

static int member_var1 = 0;

int get_var1(void)
{
   return member_var1;
}

“static”关键字将确保您的成员变量保持成员变量而不是全局变量。

接下来的问题是如何识别什么是通用代码,什么不是。我不确定是否有任何防弹方法。您的主文件很少重用或重载。 (所以继续将成员变量放入其中。)

对于其他任何事情,我更喜欢这样的事情:

struct my_state
{
   int var1;
}

int do_some_function(struct my_state* state, int some_value)
{
   state->var1 = 0;
}