Вы можете использовать понимание списка:
>>> s = 'hi'
>>> [ord(c) for c in s]
[104, 105]
Правильная интерпретация extern заключается в том, что вы сообщаете что-то компилятору. Вы сообщаете компилятору, что, несмотря на то, что он не присутствует прямо сейчас, объявленная переменная каким-то образом будет найдена компоновщиком (как правило, в другом объекте (файле)). Компилятор тогда будет счастливым парнем, чтобы найти все и собрать его вместе, были ли у вас некоторые объявления extern или нет.
ключевое слово extern используется с переменной для ее идентификации как глобальной переменной.
Оно также означает, что вы можете использовать переменную, объявленную с использованием ключевого слова extern, в любом файл, хотя он объявлен / определен в другом файле.
blockquote>
Extern - это ключевое слово, которое вы используете, чтобы объявить, что сама переменная находится в другой единицы перевода.
Таким образом, вы можете решить использовать переменную в блоке трансляции, а затем получить доступ к ней из другой, затем в второй, который вы объявляете как extern, и символ будет разрешен компоновщиком.
Если вы не объявите его как extern, вы получите две переменные, которые будут одинаковыми, но не связаны вообще, и ошибка нескольких определений переменной.
extern сообщает компилятору доверять вам, что память для этой переменной объявлена в другом месте, поэтому она не пытается выделить / проверить память.
Поэтому вы можете скомпилировать файл, который ссылается на extern, но вы не можете связать, если эта память не была объявлена где-то.
Полезно для глобальных переменных и библиотек, но опасно потому что компоновщик не устанавливает проверку.
Мне нравится думать о переменной extern в качестве обещания, которое вы делаете в компиляторе.
Когда встречается с extern, компилятор может узнать только его тип, а не там, где он «живет», поэтому он не может разрешить ссылку.
Вы говорите: «Поверьте мне. В момент ссылки эта ссылка будет разрешаемой».
Реализация GCC ELF Linux
main.c
:
#include <stdio.h>
int not_extern_int = 1;
extern int extern_int;
void main() {
printf("%d\n", not_extern_int);
printf("%d\n", extern_int);
}
Скомпилировать и декомпилировать:
gcc -c main.c
readelf -s main.o
Выход содержит:
Num: Value Size Type Bind Vis Ndx Name
9: 0000000000000000 4 OBJECT GLOBAL DEFAULT 3 not_extern_int
12: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND extern_int
В главе System V ABI Update ELF spec главу «Таблица символов» объясняется:
SHN_UNDEF Этот индекс таблицы разделов означает, что символ не определен. Когда редактор ссылок объединяет этот объектный файл с другим, который определяет указанный символ, ссылки этого файла на символ будут связаны с фактическим определением.
, который в основном является поведением, которое дает стандарт C to
extern
.С этого момента задача компоновщика заключается в создании окончательной программы, но информация
extern
уже извлечена из исходного кода в объектный файл.Проверено на GCC 4.8.
readelf
или nm
может быть полезным, вы не объяснили основы использования extern
и не выполнили первую программу с фактическим определением. Ваш код даже не использует notExtern
. Проблема с номенклатурой тоже: хотя notExtern
здесь определен, а не объявлен с помощью extern
, это внешняя переменная, к которой могут обращаться другие исходные файлы, если эти единицы перевода содержали подходящее объявление (для чего понадобилось бы extern int notExtern;
!).
– Jonathan Leffler
30 August 2015 в 14:57
notExtern
было уродливо, исправлено. О номенклатуре, дайте мне знать, если у вас есть лучшее имя. Конечно, это не было бы хорошим именем для реальной программы, но я думаю, что здесь хорошо подходит дидактическая роль.
– Ciro Santilli 新疆改造中心 六四事件 法轮功
2 September 2015 в 14:52
global_def
для переменной, указанной здесь, и extern_ref
для переменной, определенной в каком-либо другом модуле? Имеют ли они соответственно четкую симметрию? Вы все еще получаете int extern_ref = 57;
или что-то подобное в файле, где он определен, поэтому имя не совсем идеально, но в контексте одного исходного файла это разумный выбор. Мне кажется, что extern int global_def;
в заголовке не так много проблемы. Конечно, конечно.
– Jonathan Leffler
2 September 2015 в 14:56
Добавление extern
превращает определение переменной в объявление переменной . См. этот поток относительно того, в чем разница между объявлением и определением.
int foo
и extern int foo
(область файла)? Оба являются декларацией, не так ли?
– user
8 November 2012 в 21:07
В C переменная внутри файла say example.c предоставляется локальная область. Компилятор ожидает, что переменная будет иметь свое определение внутри одного и того же файла example.c, и когда он не найдет то же самое, это вызовет ошибку. Функция, с другой стороны, имеет глобальную область по умолчанию. Таким образом, вам не нужно явно упоминать компилятор «посмотрите чувак ... вы можете найти определение этой функции здесь». Для функции, содержащей файл, содержащий его объявление, достаточно. (Файл, который вы на самом деле называете заголовочным файлом). Например, рассмотрим следующие 2 файла: example.c
#include<stdio.h>
extern int a;
main(){
printf("The value of a is <%d>\n",a);
}
example1.c
int a = 5;
Теперь, когда вы скомпилируете два файла вместе, используйте следующие команды:
шаг 1) cc -o ex example.c example1.c, этап 2) ./ ex
Вы получаете следующий вывод: значение a равно & lt; 5 & gt;
extern
просто означает, что переменная определена в другом месте (например, в другом файле).
file3a.h
является #ifdef DEFINE_VARIABLES / #define EXTERN / #else / #define EXTERN extern / #endif
, удаление комментариев и использование косой черты для обозначения концов строк. Если указано DEFINE_VARIABLES
, то переменные не должны иметь префикс extern
, который будет отмечать их как декларации вместо определений. Это, в свою очередь, означает, что компилятор будет выделять пространство для переменных, а не просто записывать их существование.
– Jonathan Leffler
16 January 2013 в 04:14
extern
должно быть в заголовке, а не в first.c
, так что если тип изменяется, объявление также изменится. Кроме того, заголовок, объявляющий переменную, должен быть включен second.c
, чтобы убедиться, что определение соответствует декларации. Объявление в заголовке - это клей, который держит его вместе; он позволяет скомпилировать файлы отдельно, но обеспечивает согласованное представление типа глобальной переменной.
– Jonathan Leffler
2 September 2015 в 15:09
Переменная extern
- это объявление (благодаря sbi для коррекции) переменной, которая определена в другой единицы перевода. Это означает, что хранилище для переменной выделено в другом файле.
Скажем, у вас есть два файла .c
test1.c
и test2.c
. Если вы определяете глобальную переменную int test1_var;
в test1.c
и хотите получить доступ к этой переменной в test2.c
, вы должны использовать extern int test1_var;
в test2.c
.
Полный образец:
$ cat test1.c
int test1_var = 5;
$ cat test2.c
#include <stdio.h>
extern int test1_var;
int main(void) {
printf("test1_var = %d\n", test1_var);
return 0;
}
$ gcc test1.c test2.c -o test
$ ./test
test1_var = 5
extern int test1_var;
на int test1_var;
, компоновщик (gcc 5.4.0) все еще проходит. Итак, действительно ли extern
нужен в этом случае?
– radiohead
24 March 2018 в 04:15
extern
является общим расширением, которое часто работает, и, в частности, работает с GCC (но GCC далеко не единственный компилятор, который поддерживает это, он распространен на Unix-системах). Вы можете найти «J.5.11». или раздел «Не очень хороший способ». в моем ответе (я знаю - это is i> long), и текст рядом с ним объясняет (или пытается это сделать).
– Jonathan Leffler
16 June 2018 в 19:44