TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #482 8.45K
Линкуем массивы к объектам
#опытным

Опытные читатели могли заметить кое-что странное в этом посте. И заметили кстати. Изначально cin, cout и тд определены, как простые массивы. А в iostream они уже становятся объектами потоков и линкуются как онные. То есть в одной единице трансляции

extern std::ostream cout;
extern std::istream cin;
...


А в другой

 // Standard stream objects.
// NB: Iff <iostream> is included, these definitions become wonky.
typedef char fake_istream[sizeof(istream)]
__attribute__ ((aligned(__alignof__(istream))));
typedef char fake_ostream[sizeof(ostream)]
__attribute__ ((aligned(__alignof__(ostream))));
fake_istream cin;
fake_ostream cout;
fake_ostream cerr;
fake_ostream clog;


Что за приколы такие? Почему массивы нормально линкуются на объекты кастомных классов?

В С++ кстати запрещены такие фокусы. Типы объявления и определения сущности должны совпадать.

Все потому что линкер особо не заботится о типах, выравнивании и даже особо о размерах объектов. То есть я буквально могу прилинковать объект одного кастомного класса к другому и мне никто никакого предупреждения не влепит. То есть такой код вполне нормально компилится:

// header.hpp
#pragma once

struct TwoFields {
int a;
int b;
};

struct ThreeFields {
char a;
int b;
long long c;
};

// source.cpp

ThreeFields test = {1, 2, 3};

// main.cpp

#include <iostream>
#include "header.hpp"

extern TwoFields test;

int main() {
std::cout << test.a << " " << test.b << std::endl;
}


На консоли появится "1 2". Но ни типы, ни размеры типов, ни выравнивания у объектов из объявления и определения не совпадают. Поэтому здесь явное UB.

Но в исходниках GCC так удачно сложилось, что массивы реально представляют собой идеальные сосуды для объектов io-потоков. На них даже сконструировали реальные объекты. Поэтому такие массивы можно интерпретировать как сами объекты.

Это, естественно, все непереносимо. Но поговорка "спички детям - не игрушка" подходит только для тех, кто плохо понимает, что делает. А разработчики компилятора не из этих ребят.

Take conscious risks. Stay cool.

#cppcore #compiler
  • 🔥 47
  • 🤯 10
  • ❤‍🔥 4
  • 👍 4
  • ❤ 2
More from @grokaemcpp
  1. Oct 14, 2026​​Что внутри std::condition_variable? #опытным Более менее все знакомы с примитивом синхро…
  2. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  3. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  4. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  5. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  6. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →