2013-08-18 2 views
1

Im ищет лучшее понимание следующих 3 примеров.Разный контент & a

Это мои вопросы к следующим примерам кода.

  • Ex. 1. Пример имеет смысл, он выдает адрес, из которого хранится int a .
  • Исх. 2. Делает немного меньше смысла. Я думаю, что это , потому что сам шар указывает на символ?
  • Исх. 3. Смущает меня. В вывод первого выходного сигнала символа всегда сохраняется на символе. Но какие добавочные символы и почему они появляются после сохранения & a указателю на символ?

И наконец, как я могу вывести адрес ячейки памяти, где сохраняется переменная символа?

Ex. 1

main(void) 
{ 
    int a = 1; 
    cout << &a; 
} 

Вывод адрес памяти Ex. 0x7fff4241b7b4

Ex 2.

main(void) 
{ 
    char a = 'a'; 
    cout << &a; 
} 

Выводит символ а. ех. a

Ex. 3.

main(void) 
{ 
    char a = 'a'; 
    char *b = &a; 
    cout << &a; 
} 

Выходы а:

+1

Второе и третье - неопределенное поведение. 'operator <<' имеет перегрузку для 'const char *' из-за строк. – chris

+1

Это больше связано с перегрузками 'std :: ostream & operator <<', чем с поведением '&'. – juanchopanza

+2

@chris: Почему третий выход должен быть неопределенным? Он кажется совершенно определенным: нет ничего плохого в назначении адреса символа 'char' указателю и указанию адреса указателя. Тем не менее, я сомневаюсь, что выход третьей программы - это то, что она утверждала, вероятно, это больше похоже на «0x7fff5f174a68». –

ответ

6

Первый указатель соответствующий тому operator<<(const void*), который выводит значение указателя; второе и третье совпадение operator<<(const char*), которое выведет строку с нулевым завершением.

char a - значение в стеке, поэтому полностью не определено, являются ли байты после первого байта нулевыми или нет, к счастью, в среднем случае за ним следует нулевой байт, но в третьем случае следующие байты не являются нулевыми байтами, и вы получаете сломанные символы UTF-8. Тот факт, что вы устанавливаете указатель, не влияет на работу программы, но кадр стека настраивается по-разному, и, например, GCC испускает код операции ассемблера movb $97, -9(%rbp) для установки байта в стеке, помещая символ в не выровненный адрес ,Макета стека на моем компьютере это (64 бит)

| x | x | x | x | x | x | a | b | b | b | b | b | b | b | b | 
                  ^
                  RPB 

Таким образом a затем на стек непосредственно с последующим значением указателя б; мусор, который я вижу при запуске на моей машине, исходит из этого значения указателя. В самом деле, если я изменить экс 3 в

#include <iostream> 

int main(void) 
{ 
    char a = 'a'; 
    long b = 0x68676665646362l; 
    std::cout << &a; 
} 

я получаю выход

abcdefgh 

Конечно, это пример неопределенного поведения; компилировать с использованием другого компилятора, запускать на другой платформе, и программа может в соответствии со стандартами также разбиться, распечатать полный текст Гамлета или добиться самосознания.

+0

Спасибо, это очищает ее. –

2

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

Если вы хотите напечатать фактический указатель, то вы должны привести указатель:

std::cout << static_cast<void*>(&a) << '\n'; 
+2

Я бы 'static_cast'. – aschepler

+0

@aschepler Вы правы, в этом случае это лучшее. –

+0

@JoachimPileborg, спасибо, что это имеет смысл. У меня была ошибка в ex. 3. Не могли бы вы еще раз взглянуть на это? Я растерялся, зачем устанавливать * b = & a; изменяет cout of & a –

Смежные вопросы