如何使用纯C在main()函数中初始化全局常量变量?

时间:2018-10-01 03:12:25

标签: c parameters global-variables const

我该如何进行全局常量初始化?有可能吗?还是有另一种方法可以做我想要的?我的意思是我需要从main()获得的全局参数,并且它们必须是常量。

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

const int var;

int main(int argc, char *argv[]) {
    var = atoi(argv[1]);

    /* ... */

    return 0;
}

3 个答案:

答案 0 :(得分:3)

  

我需要从main()获取的全局参数,并且它们必须是常量。

没有OP想要的直接执行的便携式方法。

代码需要不同的读取和写入权限。有效地隐藏了对真实数据的访问。


一种封闭的解决方案,它可以通过另一个文件中定义的函数来设置和获取数据。那么一旦设置就无法更改数据,只能设置一次。

main_var.h

int main_var_get(void);
void main_var_set(int v);

main_var.c

#include <stdlib.h>
#include "main_var.h"

static int var;  // This could instead be a struct of many members.
                 // Or a pointer to a struct with many members.
static int var_init;

int main_var_get(void) {
  if (!var_init) {
    // Handle call of get before set, perhaps exit or return default value
    exit(EXIT_FAILURE);
  }
  return var;
}

void main_var_set(int v) {
  if (var_init) {
    // Handle 2nd set, perhaps exit or ignore
    exit(EXIT_FAILURE);
  }
  var = v;
  var_init = 1;
}

main.c

#include <stdio.h>
#include "main_var.h"

int main(void) {
  main_var_set(42);
  ...
  printf("%d\n", main_var_get());
}

另一种方法是使用const int *。设置之前的访问与取消引用NULL相同,即为否。尝试写*main_var_addr是UB,就像写任何const对象一样。

main_var.h

extern const int *main_var_addr;
void main_var_set(int v);

main_var.c

#include <stdlib.h>
#include "main_var.h"

const int *main_var_addr = NULL;
static int var;

void main_var_set(int v) {
  if (main_var_addr) {
    // Handle 2nd set attempt, perhaps exit or ignore
    exit(EXIT_FAILURE);
  }
  var = v;
  main_var_addr = &var
}

main.c

#include <stdio.h>
#include "main_var.h"

int main(void) {
  main_var_set(42);
  ...
  printf("%d\n", *main_var_addr);
}

答案 1 :(得分:1)

我不认为C允许您在其他地方初始化常量。但是,您可以将var从const更改为static。

答案 2 :(得分:0)

这是不可能的,实际上const并不意味着变量在C中是恒定的,仅意味着不允许您更改变量的值,但是其他人可以。

全局值是在主运行之前初始化的,这意味着您无法在运行时进行初始化,这种初始化是如何实现的,因此是实现行为,因此没有“纯C”的方式来完成您要的操作。

但是,我不明白为什么不能封装全局变量:

my_var.h:

int init_my_var(int argc, char **argv);
int get_my_var(void);

my_var.c

#include <stdlib.h>
#include <limits.h>
#include <errno.h>

static int var;

int init_my_var(int argc, char **argv) {
#ifndef NDEBUG
#include <stdbool.h>
#include <assert.h>
    {
        static bool first = true;
        assert(first);
        first = false;
    }
#endif

    if (argc < 2) {
        return 1;
    }
    errno = 0;
    long ret = strtol(argv[1], NULL, 10);
    if (errno || (ret < INT_MIN || ret > INT_MAX)) {
        return 2;
    }
    var = (int)ret;

    return 0;
}

int get_my_var(void) {
    return var;
}

main.c:

#include <stdio.h>

int main(void) {
    printf("%d\n", get_my_var());
    if (init_my_var(2, (char *[]){"", "42"})) {
        return EXIT_FAILURE;
    }
    printf("%d\n", get_my_var());
    if (init_my_var(2, (char *[]){"", "0"})) {
        return EXIT_FAILURE;
    }
}