Как можно получить доступ к внешнему указателю на строковый литерал, объявленный в одном C-файле, в другом C-файле? - PullRequest
0 голосов
/ 15 апреля 2019

Я получаю свои морские ноги с C, и мне нужен строковый литерал, который обнаружен в функции main в одном файле .c, чтобы быть доступным в совершенно другом файле .c.

То, что я пробовал: я объявляю указатель на строковый литерал как extern в заголовке, определяю его для одного .c файла и пытаюсь получить доступ к литералу во втором .c файле.Компиляция не удалась из-за отсутствия определения во втором (доступном) файле.

Вкратце:

file1.h :

extern char *global;

file1.c :

#include "file1.h"

int main() {
     //some code
     extern char *global = some_struct->data;
     //more code
}

file2.c :

#include "file1.h"

int do_stuff() {
     //some code
     some_function(global);
     //more code
}

Я ожидал, что это скомпилируется,поскольку global объявлено в file1.h, определено в file1.c, а его значение доступно в file2.c.Однако компиляция file2.c завершается неудачно для неопределенной переменной.

При необходимости, функция main в file1.c всегда является первой функцией, запущенной в программе.

Ответы [ 2 ]

2 голосов
/ 15 апреля 2019

in main

     extern char *global = some_struct->data;

неверно, если вы хотите присвоить global do:

     global = some_struct->data;

и некоторые, где в глобальной области видимости вам нужно определить global :

char *global;

Так, например, main становится:

#include "file1.h"

char *global;

int main() {
     //some code
     global = some_struct->data;
     //more code
}
0 голосов
/ 15 апреля 2019

Ты рядом, но не совсем там. Глобальная переменная также должна быть определена в глобальной области видимости, и вы сталкиваетесь с разницей между декларацией и определением (которую легко ошибиться наоборот, но слова не так важны, как идея). Как правило, ваши операторы, которые вводят переменную, одновременно объявляют и определяют, но не так с глобальными переменными, которые разделяются между модулями, как это:

В вашем file1.h вы правильно объявляете переменную char* в глобальной области видимости. Любой, кто включает этот файл (например, file2.c), «увидит», что переменная с таким именем должна существовать, и все модули будут скомпилированы без ошибок, а ключевое слово extern явно указывает, что вы только заявляете, что это существует, а не создают хранилище. для этого еще. Это то, что вы хотите, потому что вы не хотите случайно создавать несколько конфликтующих глобальных переменных с этим именем. Когда скомпилированные модули в конечном итоге будут связаны друг с другом, компоновщик будет искать фактическое пространство памяти, выделенное для глобального, и правильно соединит все ссылки.

Но в вашем случае это не произойдет правильно, потому что, хотя вы объявили миру, что этот глобал существует, вы еще не создали хранилище для переменной!

Вам все еще нужно сделать это в глобальной области видимости (вне функций) в file1.h:

char * global; 

Это создает фактическую переменную с именем, совпадающим с объявлением extern, и поэтому компоновщик сможет правильно собрать ваши модули.

Итак

#include "file1.h"

// Define global:
char * global;

int main() {
     // Assign a value to the global variable:
     global = some_struct->data;

     //more code
}

Обратите внимание, что вы не переопределяете extern или что-либо еще в этом файле, и вы не переопределяете тип global внутри main, потому что он уже существует, и вы можете присвоить ему или посмотреть на него значение. Вы также не используете ключевое слово extern здесь - это «домашний» модуль для этой переменной.

Объявление и определение обычно выполняются одновременно, например, когда вы объявляете локальные переменные внутри функции. Глобальные переменные, доступные из разных модулей, полагаются на разделение работы на две отдельные идеи, чтобы и ваши коллеги, и компилятор, и инструментальные средства компоновщика не были сбиты с толку вашими намерениями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...