символ и символ * (указатель)

Я хотел бы понять, как работают указатели, поэтому я создал эту небольшую программу. Прежде всего я создаю указатель p, который указывает на символ.

Первый вопрос на данный момент. Если я создаю указатель, его значение является адресом памяти (если я указываю на объект без указателя), но на этот раз это «ха-ха» в моем примере. Почему это работает в char *? И как я могу добавить ценность к нему с помощью cin >> p?

Мой второй вопрос заключается в том, что я создал символ q, который имеет значение указателя * p в том месте, где я его создал. НО его значение и адрес тоже «h», но почему? Это должен быть адрес памяти этого объекта char! Это бессмысленно: D (mingw — gcc)

#include <iostream>

int main()
{
/* char *p;
cin >> p;                      //forexample: haha */

char * p = "haha";
char q = *p;
std::cout << "&q = " << &q << std::endl;   //&q = h
std::cout << "q  = " <<  q << std::endl;   //q = h

return 0;
}

Еще: если я сначала выделю память с помощью символа a [100]; char * p = a; затем &q = h »ŢĹ, так что« h »и какой-то беспорядок. но это должен быть адрес памяти! и мой вопрос, почему это не адрес тогда?

5

Решение

Думать о char* p; по адресу в памяти. Вы не инициализировали этот указатель, поэтому он ни на что не указывает, вы не можете его использовать.

Всегда быть в безопасности:
либо инициализировать указатель на ноль:

char *p = 0; // nullptr in C++11

или инициализировать к некоторому автоматическому

void foo() {
char a[100];
char *p = a;
}

или глобальная память:

char a[100];
void foo() {
char *p = a;
}

или получить динамическую память:

char* p = new char [100];

Затем вы можете использовать p (если не NULL) для чтения данных и чтения из p …


За ваше недоразумение operator >> (std::istream&, char* p), Этот оператор ожидает, что p указывает на некоторую память (автоматическую, глобальную, динамическую — неважно) — она ​​не выделяет память сама. Он просто читает символы из входного потока до пробелов и копирует их в память, указанную p — но p уже должен указывать на некоторую память.


Для получения адреса char q;, Конечно, вы можете взять адрес q: &qи это типа char* p, Но &q отличается тем, что p, и это q=*p просто копирует первый символ, указанный p в q, он не может изменить адрес q — его адрес неизменен. За cout << &qoperator << (ostream&, char* p) ожидает, что p указывает на завершенную строку NULL — и &q указывает на память, содержащую "H" но что после этого персонажа никто не знает — так вы получите немного мусора на экране. использование cout << q печатать один символ.

6

Другие решения

Первое, что нужно изучить и всегда помнить об указателях, — это выделить для них память, иначе ваша программа не будет работать должным образом.

Ваш код должен быть модифицирован следующим образом, чтобы выделить память, чтобы «cin» мог записать пользовательский ввод в выделенную память:

int main() {
char *p = new char[1024];      // allocate memory so cin
cin >> p;                      //forexample: haha
char q = *p;
cout << "&q = " << &q << endl;
cout << "q = " << q << endl;
return 0;
}

Теперь указатель символа — это переменная, указывающая на позицию в памяти, содержащую набор символов (необязательно один символ, может быть, больше одного, может быть, ни одного, как в случае специального значения null), в то время как символьная переменная фактически содержит один символ (не набор символов).

Основными операторами при работе с указателями является &(адрес) и * (значение в). & извлекает адрес переменной, поэтому если у нас есть [char q;], то [&q] будет указатель на символ. С другой стороны, * извлекает значение по указанному указателю, поэтому, если у нас есть [char * p;], тогда [* p] будет символом в памяти, на который указывает p.

Теперь вернемся к вашему примеру, комментарии встроены для иллюстрации

int main() {
// allocate a place of 1024 character in memory
// and let p points to that place
char *p = new char[1024];

// call cin to read input from the user and save
// it in memory at the location pointed to by p
// NOTE: cin would put an extra NULL character
// at the end to terminate the string
cin >> p;                      //forexample: haha

// Now p would be pointing to a piece of memory like this
// [h] [a] [h] [a] [\0]

// use the value at operator to de-reference the pointer
// p, the result would be a single character which
// will be the first character in memory p is pointing at
char q = *p;

// printing the value of (the address of q)
// Note you have a problem here as cout will
// be handling the memory starting at the address
// of q as a string while it is not, so you
// will get a string starting with "h" and followed
// by whatever is there in memory by the time of execution
cout << "&q = " << &q << endl;

// printing the value of the character q
cout << "q = " << q << endl;
return 0;
}

Я надеюсь, что это помогает

2

Вы должны иметь что-то вроде:

#include <iostream>
using namespace std;

в верхней части вашей программы. Или может опустить using и обратитесь к std::cin а также std::cout,

int main() {
char *p;

p это указатель, но вы его не инициализировали, поэтому он может указывать куда угодно или никуда. Вам нужно инициализировать его, например, с помощью:

p = new char[100];

    cin >> p;                      //forexample: haha

Хорошо если вы инициализировали p указать куда-то — за исключением того, что вы можете переполнить буфер, на который он указывает, если вы вводите слишком много данных. Это нормально для такой простой тестовой программы, но на практике вы захотите принять меры, чтобы ее избежать.

    char q = *p;
cout << "&q = " << &q << endl; //&q = h

&q имеет тип char*указатель на char, Отправка char* значение для cout не печатает значение указателя (адрес памяти); он печатает строку, на которую указывает. (Хотя я получаю некоторые странные результаты, когда запускаю его сам; возможно, я что-то упускаю.) Если вы хотите увидеть значение указателя, приведите его к void*:

count << "&q = " << (void*)&q << endl;

(Или вы можете использовать одно из специфических для C ++ приведений; я не уверен, что лучше.)

    cout << "q = " << q << endl;   //q = h

Вот q это просто char, так что это печатает его значение как символ: h,

    return 0;
}
1

строковый литерал будет храниться в разделе .rdata, который будет доступен только для чтения, поэтому чтение в него с помощью std cin приведет к сбою программы

Второе, когда вы пишете это:

char *p = "some text";

тогда указатель p указывает на выделенную и доступную только для чтения память, так как секция rdata будет обязательно выделена и подготовлена ​​загрузчиком Windows, но, как я сказал, .rdata не может быть изменена

тогда, когда вы пишете это:

char q = *p;

Вы назначаете q только первому символу в p, так как * возвращает значение, на которое в данный момент указывает указатель, поэтому, если вы попробовали это:

++p;
q = *p;

q будет содержать «a», а не «h», так как указатель является адресом, который указывает на несколько символов, начиная с первого, поэтому при увеличении на единицу указатель будет указывать на второй символ, а q будет содержать это значение

0

Лучший способ сделать это:

    int arraySize;
cin>>arraySize;
char *a=new char[arraySize];
cin >> a;
0
По вопросам рекламы [email protected]