2012-02-02 3 views
1

У меня есть следующий код C++Адрес ссылочной переменной в C++

#include <iostream> 

using namespace std; 

int a=100; 
int &b = a; 

int main (int argc, char ** argv) 
{ 

    cout << " a "<<a<<" b"<<b<<endl; 
    b = 200; 
    cout <<"a "<<a<<endl; 
} 

Я хотел бы видеть адрес одновременно, и б в таблице символов объектного файла?

#gcc -g -o ref ref.cpp -lstdc++ 

Есть инструменты, такие как objdump, readelf. но я не знаком с этими инструментами. Просьба указать способ определения адреса а и b в объектном файле [т.е.: в таблице символов]

ПРИМЕЧАНИЕ. Я редактировал для перемещения переменных из локального в глобальное.

+1

Что вы подразумеваете под их адресом в объектном файле? Это стек (автоматические) переменные. Они не должны появляться нигде в таблице символов. (Только в отладочной информации.) – Mat

+0

@Mat, моя ошибка. Я сделал обе переменные глобальными. – Whoami

ответ

4

Адрес ссылочной переменной такой же, как адрес объекта, к которому он относится.
т.е:

&b == &a 

И это хорошо определяется стандартом и всегда будет верным.
Что пытаются достичь?

+0

Действительно. Но это на самом деле не отвечает на вопрос OP ... –

+0

@OliCharlesworth: Да, я знаю, что он не отвечает на Q напрямую, но нет реальной потребности в Q, это хорошо определено и всегда будет true.I чувствую, что ОП пытается доказать себе факт, который уже хорошо известен. Как бы то ни было, во-вторых, я удалю этот ответ, если ОП осознает этот факт и так говорит. –

+0

Я хотел бы видеть, как ссылки сделаны в ассемблере. – Whoami

0

Это локальные переменные, которые выделяются в стеке. Память и, следовательно, адрес получаются при запуске программы.

Вы не получите адрес из объектного файла.

0

Единственный способ увидеть адрес действительно с помощью таких инструментов, как objdump, но вы никогда не увидите адрес локальных переменных. Они не существуют во время компиляции, выделяются в стек во время выполнения. Единственное, что вы увидите в exe, это asm/машинный код, который выполняет push или sub sp, который является распределением.

Если вы измените свою программу:

#include <iostream> 

using namespace std; 

int main (int argc, char ** argv) 
{ 
    static int a=100; 
    static int &b = a; 
    cout << " a "<<a<<" b"<<b<<endl; 
    b = 200; 
    cout <<"a "<<a<<endl; 
} 

затем после компиляции сделать:

objdump -t реф | Данные GREP

, и вы увидите:

080488a8 l d .rodata  00000000    .rodata 
08049a94 l d .data   00000000    .data 
080488bc l  O .rodata  00000004    _ZZ4mainE6b 
08049a9c l  O .data   00000004    _ZZ4mainE6a 
08049a94 w  .data   00000000    data_start 
080488a8 g  O .rodata  00000004    _fp_hw 
080488ac g  O .rodata  00000004    _IO_stdin_used 
08049a94 g  .data   00000000    __data_start 
08049a98 g  O .data   00000000    .hidden __dso_handle 
08049aa0 g  *ABS*   00000000    _edata 

Переменные вы ищете являются _ZZ4mainE6a _ZZ4mainE6b (это их исковерканные имена).

EDIT: для текущей версии вашего образца кода с & b в качестве глобальных символов, будет отображаться .text и b .rodata, поэтому теперь вам нужно будет использовать «текст» в grep-фильтре, чтобы увидеть ,

+0

Спасибо. Кстати, из такого вывода мы можем разобраться, если обе переменные указывают на один и тот же адрес ?. – Whoami

+0

Нет, поскольку адрес a - это адрес его значения int, а адрес b - адрес адреса (который во время выполнения будет содержать адрес a). Но вы увидите, что значение b является адресом a, если вы посмотрите на смещение b в разделе .rodata, сбрасываемом objdump -D (обратите внимание, что порядок байтов будет инвертирован, так как вы немного -endian machine) –

+0

Также обратите внимание, что все адреса, содержащиеся в исполняемом файле, фактически являются смещениями, а не фактическими адресами. При запуске программы они будут добавлены на базовый адрес процесса для создания эффективных адресов. –

1
cout << " &a " << &a <<" &b "<< &b <<endl; 

Это покажет адрес и того и другого, и подтвердите, что они по одному адресу.

0

Вы можете использовать инструмент «nm» в конечном исполняемом файле. Как это:

$ нм -C Привет 080490ba __bss_start 080490ba _edata 080490bc _end 08048083 Т _start 08048080 т access.the.bsd.Ядро 080490ac д hbytes 080490ac д Привет $

В первой колонке выход представляет собой адрес символа, после чего идет его тип, и после этого его название.

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