Это безобидно и может быть проигнорировано.
Причина предупреждения - это то, что он говорит: LAPACK по умолчанию, который идет на macOS, немного стар, а SciPy работает с ошибкой.
Когда вы берете адрес b, вы получаете char *
. operator<<
интерпретирует это как строку C и пытается напечатать последовательность символов вместо своего адреса.
попробуйте cout << "address of char :" << (void *) &b << endl
.
[EDIT] Как сказал Томек, более подходящим для использования в этом случае является static_cast
, что является более безопасной альтернативой. Вот версия, которая использует его вместо C-стиля:
cout << "address of char :" << static_cast<void *>(&b) << endl;
Есть два вопроса:
Печать указателей будет печатать адрес для кнопки int*
и string*
, но распечатает содержимое для char*
, поскольку в operator<<
имеется специальная перегрузка. Если вам нужен адрес, используйте: static_cast<const void *>(&c);
int
и string
равна 8
На вашей платформе sizeof(int)
есть 4
, а sizeof(char)
- 1
, поэтому вам действительно нужно спросить, почему 8
не 5
. Причина в том, что строка выравнивается по 4-байтовой границе. Машины работают со словами, а не с байтами, и работают быстрее, если слова не поэтому «разделяют» несколько байтов здесь и несколько байтов. Это называется выравниванием
. Ваша система, вероятно, выравнивается с 4-байтовыми границами. Если у вас 64-разрядная система с 64-битными целыми числами, разница будет 16.
(Примечание: 64-разрядная система обычно относится к размеру указателя, а не к int. Таким образом, 64- битной системы с 4-байтовым int все равно будет иметь значение 8 как 4 + 1 = 5, но округляется до 8. Если sizeof (int) равно 8, тогда 8 + 1 = 9, но это округляет до 16)
hrnt прав насчет причины пробела: &b
имеет тип char*
и поэтому печатается как строка до первого нулевого байта. Предположительно b
равно 0. Если вы установите b
на, скажем, «A», тогда вы должны ожидать, что распечатка будет строкой, начинающейся с «A» и продолжающейся с мусором до следующего нулевого байта. Используйте static_cast<void*>(&b)
для печати в качестве адреса.
Для вашего второго вопроса &c - &i
равно 8, поскольку размер int равен 4, символ равен 1, а строка начинается с следующая 8-байтная граница (вы, вероятно, на 64-битной системе). Каждый тип имеет определенное выравнивание, а C ++ выравнивает поля в структуре в соответствии с ним, соответственно добавляя дополнение. (Правило большого пальца состоит в том, что примитивное поле размера N выровнено с кратным N.) В частности, после b
вы можете добавить еще 3 поля char
, не затрагивая адрес &c
.
Для второй проблемы - компилятор по умолчанию будет содержать элементы структуры пэда. По умолчанию используется пэд sizeof(int)
, 4 байта (на большинстве архитектур). Вот почему int
, за которым следует char
, будет иметь 8 байтов в структуре, поэтому член string
находится со смещением 8.
Чтобы отключить дополнение, используйте #pragma pack(x)
, где x - размер пэда в байтах.
int
равным 4 байтам.
– Muggen
1 February 2011 в 10:31
sizeof(int)
- собственный размер процессора. На 32-битном процессоре это 4 байта.
– Eli Iser
1 February 2011 в 10:35
int
- от адреса от 0 до 3. Значение char
должно быть от 4 до 5, а вместо этого - от 4 до 7. Наконец, string
начинается с 8.
– Eli Iser
1 February 2011 в 10:36
Поскольку, когда вы передаете char*
в std::ostream
, он печатает строку C-style (т. е.: char, char*
), на которую указывает.
Помните, что "hello"
a char*
.
char[6]
и распадается в char*
при использовании.
– peoro
1 February 2011 в 12:38
char[6]
только в C, но в C ++ это const char[6]
. Интересно, что он все еще может распадаться на char *
, хотя (обратная совместимость с C).
– hrnt
1 February 2011 в 13:23
Когда вы передаете адрес символа в ostream, он интерпретирует это как адрес первого символа строки ASCIIZ «C-style» и пытается напечатать предполагаемую строку. У вас нет терминатора NUL, поэтому вывод будет продолжать читать из памяти до тех пор, пока он не найдет его, или ОС не отключит его для чтения с недопустимого адреса. Весь мусор, который он сканирует, будет отправлен на ваш выход.
Вы можете, вероятно, получить его, чтобы отобразить адрес, который вы хотите, произведя его, как в (void*)&b
.
смещения в структуру: вы заметили, что строка размещена со смещением 8. Это, вероятно, потому, что у вас есть 32-битные int, а затем 8-битный символ, тогда компилятор решает вставить еще 3 8-битных символа, чтобы объект строки будут выровнены по 32-битной границе слова. Многие процессоры / архитектуры памяти нуждаются в указателях, int и т. Д., Чтобы быть на границах размера слова, чтобы выполнять эффективные операции над ними, и в противном случае пришлось бы выполнять еще много операций для чтения и объединения нескольких значений из памяти, прежде чем использовать значения в операции. В зависимости от вашей системы может быть, что каждый объект класса должен начинаться с границы слова, или может быть, что std::string
, в частности, начинается с указателя size_t, указателя или другого типа, который требует такого выравнивания.
Адрес char обрабатывается как строка с нулевым завершением и отображает содержимое этого адреса, что, вероятно, не определено, но в этом случае пустая строка. Если вы нажмете указатели на void *
, вы получите желаемые результаты.
Разница между something2 и чем-то состоящим из 8 должна быть выровнена и способность компилятора решить для себя, где в стеке переменные объявлены.
b = 0
автоматическое окончание null
? Также +1
– Muggen
1 February 2011 в 10:26