Как инициализировать переменную глобальной константы в функции main (), используя чистый C? - PullRequest
0 голосов
/ 01 октября 2018

Как я могу выполнить глобальную постоянную инициализацию, как это?Это вообще возможно?Или есть другой способ сделать то, что я хочу?Я имею в виду, что мне нужны глобальные параметры, полученные из main(), и они должны быть константами.

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

const int var;

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

    /* ... */

    return 0;
}

Ответы [ 3 ]

0 голосов
/ 01 октября 2018

Мне нужны глобальные параметры, полученные из 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);
}
0 голосов
/ 01 октября 2018

Это невозможно, на самом деле 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;
    }
}
0 голосов
/ 01 октября 2018

Я не думаю, что C позволяет инициализировать постоянную переменную в другом месте.Однако вы можете просто изменить var с const на static.

...