Можно ли определить константы в C во время выполнения? - PullRequest
0 голосов
/ 28 января 2020

У меня есть файл file1. c, в котором я хотел бы определить некоторые константы, если выполняются некоторые требования, для использования в другом файле, file3. c.

file1. c:

#include "header.h"

int set_constants(void) {

#ifdef EXAMPLE_MACRO
  int fd, status, size;

  fd = open(EXAMPLE_DRIVER, RD_ONLY);

  ioctl(fd, EXAMPLE_IOCTL_CHECK_SIZE, &size);

  if (size == SIZE_CONDITION) {
    /* Here i would like to define the constants 
       A, B, and C. */
  } else {
    /* Here I would like to define the constants
       A, B, and C to something else than above. */
  }
  return 0;

#endif

/* If EXAMPLE_MACRO is not defined, I would like to set
   A, B and C to something else. */
  return 0;

Функция set_constants () будет вызываться из функции init в файле 2. c, которая выполняет вызов функции в файле3. c, который использует константу A:

#include "header.h"

void file2_init(void) {
  set_constants();

  file3_function();
}

В файле 3. c я хотел бы создать глобальный массив с элементами A:

#include "header.h"

uint8_t array[A];

void file3_function(void) 
{
  /* Do something with array */
}

Я понимаю, что A , B и C не могут быть определены как макросы, поскольку переменная size неизвестна, когда макросы обрабатываются препроцессором. Можно ли было бы даже создать такие константы (используя язык C)?

Я пытался определить A, B и C как глобальные целочисленные переменные (я знаю, что они не постоянны, но пока это моя единственная идея) в file1. c, и я объявил их так в заголовочном файле header.h:

#ifndef _MY_HEADER_H_
#define _MY_HEADER_H

extern int A;
extern int B;
extern int C;

void set_constants(void);
void file3_function(void);

#endif _MY_HEADER_H_

Но тогда я получаю ошибку:

ошибка: переменно измененный «массив» в области видимости файла

массив [A] должен находиться в глобальной области видимости, мой вопрос: как мне объявить и определить A , B и C такие, что они видны для файла 3. c и не поднимают ошибку выше?

Я также пытался сделать A, B и C постоянными int, вот так;

#include "header.h" 
int set_constants(void) {

#ifdef EXAMPLE_MACRO
  int fd, status, size;

  fd = open(EXAMPLE_DRIVER, RD_ONLY);

  ioctl(fd, EXAMPLE_IOCTL_CHECK_SIZE, &size);

  if (size == SIZE_CONDITION) {

    const int A = 1;
    const int B = 1;
    const int C = 1;

  } else {

    const int A = 2;
    const int B = 2;
    const int C = 2;
  }
  return 0;

#endif

  const int A = 3;
  const int B = 3;
  const int C = 3;

  return 0;

и объявлены A, B и C до extern const int в header.h:

#ifndef _MY_HEADER_H_
#define _MY_HEADER_H

extern const int A;
extern const int B;
extern const int C;

void set_constants(void);
void file3_function(void);

#endif _MY_HEADER_H_

Но тогда Я получаю ошибку компиляции:

ошибка: объявление 'A' затеняет глобальное объявление [-Werror = shadow] const int A = 1;
В файле, включенном из file1. c : header.h: ошибка: sha здесь объявлено dowed [-Werror = shadow] extern const int A;

1 Ответ

1 голос
/ 28 января 2020

Чтобы глобальная область действия uint8_t array[A]; работала, во время компиляции должно быть известно A. Инициализированная память буквально находится в файле исполняемых объектов. [1] А такое, вы не сможете использовать uint8_t array[A];; вам нужно будет использовать динамическое выделение памяти c (например, malloc).


  1. Если оно инициализировано всеми нулевыми байтами, оно помещается на страницу памяти, которая выделяется во время выполнения , но тот факт, что это все нули, все еще должен быть известен во время компиляции, чтобы знать, как использовать этот подход.
...