Адрес указателя и значения по указателю одинаковы [дубликат]

Это безобидно и может быть проигнорировано.

Причина предупреждения - это то, что он говорит: LAPACK по умолчанию, который идет на macOS, немного стар, а SciPy работает с ошибкой.

41
задан Kevin Reid 2 June 2013 в 15:56
поделиться

8 ответов

Когда вы берете адрес b, вы получаете char *. operator<< интерпретирует это как строку C и пытается напечатать последовательность символов вместо своего адреса.

попробуйте cout << "address of char :" << (void *) &b << endl.

[EDIT] Как сказал Томек, более подходящим для использования в этом случае является static_cast, что является более безопасной альтернативой. Вот версия, которая использует его вместо C-стиля:

cout << "address of char   :" << static_cast<void *>(&b) << endl;
69
ответ дан hrnt 22 August 2018 в 10:58
поделиться
  • 1
    Я бы предложил static_cast здесь ... – Tomek 10 February 2011 в 21:16
  • 2
    Можете ли вы проиллюстрировать, почему static_cast является более безопасной альтернативой, может быть, путем примера? Я не понимаю, в чем вред при использовании void * здесь. – Vishal Sharma 10 April 2018 в 03:30

Есть два вопроса:

  • Почему он не печатает адрес для символа:

Печать указателей будет печатать адрес для кнопки 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)

23
ответ дан CashCow 22 August 2018 в 10:58
поделиться

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.

0
ответ дан DS. 22 August 2018 в 10:58
поделиться

Для второй проблемы - компилятор по умолчанию будет содержать элементы структуры пэда. По умолчанию используется пэд sizeof(int), 4 байта (на большинстве архитектур). Вот почему int, за которым следует char, будет иметь 8 байтов в структуре, поэтому член string находится со смещением 8.

Чтобы отключить дополнение, используйте #pragma pack(x), где x - размер пэда в байтах.

2
ответ дан Eli Iser 22 August 2018 в 10:58
поделиться
  • 1
    Я сомневаюсь, что упаковка будет, но адрес строки с пятибайтным смещением (во многих компиляторах) из-за требований к выравниванию. – Christopher Creutzig 1 February 2011 в 10:30
  • 2
    Разве не привязана к выравниванию данных? Кроме того, AFAIK не является стандартным для int равным 4 байтам. – Muggen 1 February 2011 в 10:31
  • 3
    @Muggen - выравнивание данных действительно зависит от платформы, но чаще всего это sizeof(int) - собственный размер процессора. На 32-битном процессоре это 4 байта. – Eli Iser 1 February 2011 в 10:35
  • 4
    @Christopher - смещение не 5 байтов, а 3. int - от адреса от 0 до 3. Значение char должно быть от 4 до 5, а вместо этого - от 4 до 7. Наконец, string начинается с 8. – Eli Iser 1 February 2011 в 10:36
  • 5
    @Eli На многих 64-битных процессорах sizeof(int) все еще 4. – KitsuneYMG 1 February 2011 в 10:44

Поскольку, когда вы передаете char* в std::ostream, он печатает строку C-style (т. е.: char, char*), на которую указывает.

Помните, что "hello" a char*.

10
ответ дан peoro 22 August 2018 в 10:58
поделиться
  • 1
    & Quot; Привет & Quot; является const char[6]. – MSalters 1 February 2011 в 11:37
  • 2
    @MSalters: нет. Это char[6] и распадается в char* при использовании. – peoro 1 February 2011 в 12:38
  • 3
    Это char[6] только в C, но в C ++ это const char[6]. Интересно, что он все еще может распадаться на char *, хотя (обратная совместимость с C). – hrnt 1 February 2011 в 13:23
  • 4
    @hrnt: Это было устаревшим в C ++ 03 и полностью удалено в C ++ 11. – Lightness Races in Orbit 10 August 2014 в 15:21

Ваш синтаксис должен быть

cout << (void*) &b
2
ответ дан Taranfx 22 August 2018 в 10:58
поделиться

Когда вы передаете адрес символа в ostream, он интерпретирует это как адрес первого символа строки ASCIIZ «C-style» и пытается напечатать предполагаемую строку. У вас нет терминатора NUL, поэтому вывод будет продолжать читать из памяти до тех пор, пока он не найдет его, или ОС не отключит его для чтения с недопустимого адреса. Весь мусор, который он сканирует, будет отправлен на ваш выход.

Вы можете, вероятно, получить его, чтобы отобразить адрес, который вы хотите, произведя его, как в (void*)&b.

смещения в структуру: вы заметили, что строка размещена со смещением 8. Это, вероятно, потому, что у вас есть 32-битные int, а затем 8-битный символ, тогда компилятор решает вставить еще 3 8-битных символа, чтобы объект строки будут выровнены по 32-битной границе слова. Многие процессоры / архитектуры памяти нуждаются в указателях, int и т. Д., Чтобы быть на границах размера слова, чтобы выполнять эффективные операции над ними, и в противном случае пришлось бы выполнять еще много операций для чтения и объединения нескольких значений из памяти, прежде чем использовать значения в операции. В зависимости от вашей системы может быть, что каждый объект класса должен начинаться с границы слова, или может быть, что std::string, в частности, начинается с указателя size_t, указателя или другого типа, который требует такого выравнивания.

13
ответ дан Tony Delroy 22 August 2018 в 10:58
поделиться

Адрес char обрабатывается как строка с нулевым завершением и отображает содержимое этого адреса, что, вероятно, не определено, но в этом случае пустая строка. Если вы нажмете указатели на void *, вы получите желаемые результаты.

Разница между something2 и чем-то состоящим из 8 должна быть выровнена и способность компилятора решить для себя, где в стеке переменные объявлены.

4
ответ дан trojanfoe 22 August 2018 в 10:58
поделиться
  • 1
    Поскольку нет конструктора, не создается автоматически конструктор по умолчанию, который устанавливает b = 0 автоматическое окончание null? Также +1 – Muggen 1 February 2011 в 10:26
  • 2
    @Muggen: код не является полным, поэтому кто знает, какой конструктор предоставляется. – trojanfoe 1 February 2011 в 10:27
  • 3
    @Muggen: Нет, сгенерированный по умолчанию ctor не будет нулевым инициализировать b. Вы должны явно это сделать; например Адрес () (как временный), новый адрес () (по сравнению с новым адресом), адрес var = Адрес (), (в 0x) Адрес var {}; (Я считаю, нужно дважды проверить) или объект Address со статической продолжительностью хранения (function / namespace / global static). – Fred Nurk 1 February 2011 в 10:28
Другие вопросы по тегам:

Похожие вопросы: