Когда я пишу следующую программу:
файл 1:
#include <stdio.h>
int global;
void print_global1() {
printf("%p\n", &global);
}
файл 2:
#include <stdio.h>
char global;
void print_global2() {
printf("%p\n", &global);
}
файл 3:
void print_global1();
void print_global2();
int main()
{
print_global1();
print_global2();
return 0;
}
вывод:
$ ./a.out
0x804a01c
0x804a01c
Вот мой вопрос:
-Wall -Wextra -ansi
...)PS: вторым вопросом является связанная архитектура/компилятор, поэтому позволяет, берут gcc или Visual C++ (для C) с международным размером как 32 бита
Править: ЭТО НЕ ВОПРОС ДЛЯ C++, НО для C!
Я использую gcc версию 4.4.1 и на Ubuntu 9.10, Вот консольный вывод компиляции:
$ ls
global_data1.c global_data2.c global_data.c
$ gcc -Wall -Wextra -ansi global_data*.c
$ ./a.out
0x804a01c
0x804a01c
or
$ gcc -Wall -Wextra -ansi -c global_data*.c
$ gcc -Wall -Wextra -ansi global_data*.o
$ ./a.out
0x804a01c
0x804a01c
Единственное, что для меня имеет смысл, это либо расширение существующего класса в структуре или библиотеке или что-то в этом роде, либо просто написание класса в другом шаблонном кодовом решении??
Отличный вопрос!
-121--3460631-Стандартные библиотеки Python не содержат классов tzinfo (но см. pep 431 ). Я могу только догадываться о причинах. Лично я думаю, что было ошибкой не включать класс tzinfo для UTC, потому что он достаточно бесспорен, чтобы иметь стандартную реализацию.
Правка: Несмотря на отсутствие реализации в библиотеке, она приведена в качестве примера в документации tzinfo
.
from datetime import timedelta, tzinfo
ZERO = timedelta(0)
# A UTC class.
class UTC(tzinfo):
"""UTC"""
def utcoffset(self, dt):
return ZERO
def tzname(self, dt):
return "UTC"
def dst(self, dt):
return ZERO
utc = UTC()
Чтобы получить текущее время в качестве осведомленного объекта datetime:
from datetime import datetime
now = datetime.now(utc)
Существует datetime.timezone.utc
в Python 3.2 +:
from datetime import datetime, timezone
now = datetime.now(timezone.utc)
-121--594472- gcc
не сообщает об ошибках/предупреждениях. Но g++
делает.
EDIT:
Выглядит так, будто C допускает предварительные определения для переменной.
В вашем случае оба глобальных определения являются предварительными, и в этом случае выбирается первое из них, видимое компоновщиком.
Измените файл на:
char global = 1; // no more tentative...but explicit.
Теперь при компиляции, как раньше, предварительный def в file1 будет игнорироваться.
Сделайте оба def явными с помощью:
int global = 1; // in file1
char global = 1; // in file2
теперь ни один из них не может быть проигнорирован, и мы получим несколько def ошибки.
Это имеет отношение к так называемому "предварительному определению" в C. Во-первых, если вы назначите global
как в file1, так и в file2 , вы получите ошибку в C. Это связано с тем, что global
больше не определено предварительно в файлах file1 и file2, оно действительно определено.
Из стандарта C (выделено мной):
Объявление идентификатора для объекта, имеющего область видимости файла без инициализатора , и без спецификатора класса хранения или с классом хранения статический спецификатор, составляет предварительное определение . Если единица трансляции содержит одно или несколько предварительных определений для идентификатора, а единица трансляции не содержит внешнего определения для этого идентификатора, то поведение будет таким же, как если бы единица трансляции содержала объявление области файла этого идентификатора с составным типом как конца единицы перевода с инициализатором, равным 0.
В вашем случае «единица перевода» (в основном) каждый исходный файл.
О «составных типах»:
Для идентификатора с внутренней или внешней связью, объявленного в области, в которой видно предыдущее объявление этого идентификатора, если в предыдущем объявлении указано внутреннее или {{1 }} внешняя связь, тип идентификатора в последующем объявлении становится составным типом .
Подробнее о предварительных определениях см. этот вопрос и ответы на него .
Похоже, в вашем случае это должно быть неопределенное поведение, потому что global
определено в конце единиц перевода, поэтому вы получаете два определения global
, и что еще хуже , они разные. Похоже, что компоновщик по умолчанию на это не жалуется.
В GNU ld есть опция под названием - warn-common
, которая предупреждает вас о нескольких предварительных определениях (общий символ - это имя компоновщика для предварительно определенных переменных):
$ gcc -Wl,--warn-common file*.c
/tmp/ccjuPGcq.o: warning: common of `global' overridden by larger common
/tmp/ccw6nFHi.o: warning: larger common is here
Если для переменной есть только (один или несколько) общих символов, она попадает в область неинициализированных данных выходного файла. Компоновщик объединяет несколько общих символов для одной и той же переменной в один символ. Если они разного размера, выбирается самый большой. Компоновщик превращает общий символ в объявление, если есть определение той же переменной.
Параметр
- warn-common
может выдавать пять видов предупреждений. Каждое предупреждение состоит из пары строк: первая описывает только что встреченный символ, а вторая описывает предыдущий встреченный символ с тем же именем.Один или оба из двух символов будут общим символом.
Компоновщик позволяет иметь дублированные внешние данные, подобные этим (хотя я удивлен, что различные типы не вызывают проблем). Какой из них вы получите, зависит от порядка следования объектных файлов в командной строке link.
Какой компилятор вы используете. Какая платформа? С g ++ я получаю
/tmp/cc8Gnf4h.o:(.bss+0x0): multiple definition of `global'
/tmp/ccDQHZn2.o:(.bss+0x0): first defined here
/usr/bin/ld: Warning: size of symbol `global' changed from 4 in a.o to 1 in b.o
AFAIR, в C ++ переменные в разных единицах перевода имеют одно и то же объявление для работы.