struct myStruct
{
int foo;
}
myStruct bar;
bar.foo = 123;
cout<<(char *) &bar<<endl;
Оператор cout выводит ‘{‘.
ASCII для 123 на самом деле равен «{» (bar.foo = 123. При изменении этого значения выводятся разные символы). Что я не понимаю, так это
cout<<(char *) &bar<<endl;
Технически следует напечатать адрес бара. Как я могу получить доступ к данным внутри структуры, используя (char *) приведение? Использование (int *) по-прежнему возвращает адрес. Я знаю, что (char *) заставляет данные располагаться побайтово, но разве это не должно влиять на адрес?
Существует перегрузка для <<
принятие const char *
, который интерпретирует операнд как указатель на строку с нулем в конце в стиле C. Это перегрузка, используемая, например,
cout << "Hello\n";
Если, как здесь, вы дадите ему указатель на что-то отличное от строки в стиле C, вы получите неопределенное поведение. На практике он будет печатать содержимое памяти побайтно, пока не достигнет нулевого байта или не выйдет из конца читаемой памяти.
<<
на char*
обрабатывает его как строку C, а не как указатель. Эта программа интерпретирует myStruct
в качестве буфера sizeof(myStruct)
байтов и полагается на порядковый номер, чтобы гарантировать, что он завершается NUL.
Чтобы распечатать адрес, просто передайте &bar
без актерского состава.
Поскольку bar является объектом структуры myStruct, его начальный адрес и начальный адрес первого члена в myStruct, т.е. bar.foo, будут одинаковыми. Так &bar даст вам начальный адрес объекта bar, а char * предоставит вам значение первого байта в этом месте адреса.
В отличие от int *
, char *
это особый вид указателей, они также используются для указания на строки ASCII, например:
const char * s = "hello world";
Для выражения (char *) &bar
результат char *
указатель, cout
поэтому напечатает строку, потому что она имеет специальный оператор для char *
это выводит строки. за int *
здесь нет оператора, есть только универсальный оператор для указателей, который печатает только адреса.
std::ostream
как правило, имеет перегрузку для operator <<
с const char *
к которому char *
будет связан с.
Эта перегрузка обрабатывает свой аргумент как завершенную нулем строку символов ASCII.
Если вам нужно вывести содержимое myStruct в выходной поток, вам нужно определить ostream << Оператор для вашей структуры, как это:
std::ostream& operator <<(std::ostream& os, const myStruct& ms)
{
os << "myStruct { foo: " << ms.foo << "\n}";
return os;
}
(char *) ничего не меняет. Структура хранится в памяти как 4 байта = sizeof (int) или 8 байтов на 64-битном ЦП, в зависимости от архитектуры процессора в порядке с прямым порядком байтов или с прямым порядком байтов (см. http://en.wikipedia.org/wiki/Endianness).
Ваш код, вероятно, работает на процессоре архитектуры x86, поэтому младший байт хранится по младшему адресу. Например, число 123 в foo будет храниться как байты 7B 00 00 00. В памяти. Ваш оператор co char * скажет компилятору использовать оператор ostream для массива char *, который используется как строка в C. Каждый байт интерпретируется как один символ, оканчивающийся на 0 байт. Байт 123 соответствует символу ASCII ‘{‘, он заканчивается байтом 00, поэтому в этом случае ваш код не потерпит крах. Другие значения могут привести к сбою вашего кода или печати байтов в стеке за пределами хранилища вашей структуры (до тех пор, пока не встретится нулевой байт или не произойдет сбой).
Надеюсь это поможет.
На самом деле ваш код печатает адрес строки переменных структуры, а не значение foo. (Char *)&bar преобразует адрес типа структуры в (char *) означает c строкового типа.
Некоторые параметры функций c, c ++ действительно принимают тип struct в качестве аргументов, поэтому нам нужно преобразовать тип struct в (char *) или (void *) в соответствии с параметрами функции.