Разница между использованием указателей символов и массивов символов

Основной вопрос.

char new_str[]=""; char * newstr; 

Если мне нужно объединить некоторые данные в него или использовать строковые функции, такие как strcat / substr / strcpy, какая разница между ними?

Я понимаю, что я должен выделить память для подхода char * (строка # 2). Хотя я не совсем уверен.

И const char * и строковые литералы одинаковы?

Мне нужно знать об этом больше. Может ли кто-нибудь указать на какой-то хороший исчерпывающий контент / материал?

Прочтите эту статью ниже:

Также см. В случае массива char, как в вашем случае, char new_str [], тогда new_str всегда укажет на базу массива. Указатель сам по себе не может быть увеличен. Да, вы можете использовать индексы для доступа к следующему new_str[3] в массиве, например: new_str[3] ;

Но в случае указателя на char, указатель может быть увеличен на new_str++ чтобы получить следующий символ в массиве.

Также я бы предложил эту статью для большей ясности.

Отличным источником для устранения путаницы является Питер Ван дер Линден, программирование экспертов C, глубокие секреты C, – что массивы и указатели не совпадают, так это то, как они адресованы в память.

С массивом,

  char new_str []; 

компилятор дал new_str адрес памяти, который известен как для компиляции, так и для времени выполнения, например 0x1234, поэтому индексация new_str проста с помощью [] . Например, new_str[4] , во время выполнения код выбирает адрес, где находится new_str , например 0x1234 (то есть адрес в физической памяти). добавив к нему спецификатор индекса [4] , 0x1234 + 0x4, тогда значение можно будет получить.

Принимая во внимание, что с указателем компилятор дает символ

  char * newstr 

адрес, например, 0x9876, но во время выполнения этот используемый адрес является схемой косвенной адресации. Предположим, что newstr был malloc’d

  newstr = malloc (10); 

, происходит то, что каждый раз, когда ссылка в коде используется для использования newstr, поскольку адрес newstr известен компилятору, то есть 0x9876, но то, что указывает newstr, является переменной. Во время выполнения код извлекает данные из физической памяти 0x9876 (т.е. newstr), но на этом адресе есть другой адрес памяти (поскольку мы его malloc’d), например 0x8765, здесь код извлекает данные из этого адреса памяти, который malloc назначается newstr, т.е. 0x8765.

char new_str[] и char *newstr используются взаимозаменяемо, поскольку индекс нулевого элемента массива распадается на указатель, и это объясняет, почему вы можете newstr[5] или *(newstr + 5) Обратите внимание, как выражение указателя используется даже хотя мы объявили char *newstr , следовательно

  *(new_str + 1) = * newstr; 

ИЛИ

  *(new_str + 1) = newstr [1]; 

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

Получите книгу, прочитайте ее и живите и вздохните. Его блестящая книга! 🙂

Это массив символов:

 char buf [1000]; 

Так, например, это не имеет никакого смысла:

 buf = &some_other_buf; 

Это связано с тем, что buf , хотя он имеет характеристики указателя типа, он уже указывает на единственное место, которое имеет для него смысл.

 char *ptr; 

С другой стороны, ptr является только указателем и может указывать где-то. Чаще всего это что-то вроде этого:

 ptr = buf; // #1: point to the beginning of buf, same as &buf[0] 

или, может быть, это:

 ptr = malloc (1000); // #2: allocate heap and point to it 

или:

 ptr = "abcdefghijklmn"; // #3: string constant 

Для всех них * ptr может быть записано до – за исключением третьего случая, когда некоторая среда компиляции определяет строковые константы, которые могут быть неприемлемыми.

 *ptr++ = 'h'; // writes into #1: buf[0], #2: first byte of heap, or // #3 overwrites "a" strcpy (ptr, "ello"); // finishes writing hello and adds a NUL 

Разница в том, что один из них является указателем, другой – массивом. Вы можете, например, массив sizeof (). Вы можете быть заинтересованы в подглядывании здесь

Если вы используете C ++, как указывают tags, вам действительно нужно использовать строки C ++, а не массивы char C.

string тип упрощает манипулирование строками.

Если по какой-то причине вы застряли с массивами char , строка:

 char new_str[] = ""; 

выделяет 1 байт пробела и помещает в него нулевой символ-ограничитель. Это тонко отличается от:

 char *new_str = ""; 

так как это может дать вам ссылку на незаписываемую память. Заявление:

 char *new_str; 

сам по себе дает вам указатель, но ничего, на что он указывает. Он также может иметь случайное значение, если оно является локальным для функции.

То, что люди склонны делать (на C, а не на C ++), – это сделать что-то вроде:

 char *new_str = malloc (100); // (remember that this has to be freed) or char new_str[100]; 

чтобы получить достаточно места.

Если вы используете функции str... , вы в основном отвечаете за то, чтобы у вас было достаточно места в массиве char , чтобы вы не получали всевозможные странные и прекрасные практики при отладке кода. Если вы используете настоящие строки C ++, для вас очень много работы.

Тип первого – char [1], второй – char *. Различные типы.

Выделите память для последнего с помощью malloc в C или new на C ++.

 char foo[] = "Bar"; // Allocates 4 bytes and fills them with // 'B', 'a', 'r', '\0'. 

Размер здесь подразумевается из строки инициализации.

Содержимое foo изменчиво. Вы можете изменить foo[i] например, где i = 0..3.

OTOH, если вы это сделаете:

 char *foo = "Bar"; 

Теперь компилятор выделяет статическую строку «Bar» в памяти readonly и не может быть изменен.

 foo[i] = 'X'; // is now undefined. 
 char new_str[]="abcd"; 

Это задает массив символов (строки) размером 5 байтов (один байт для каждого символа плюс один для нулевого терминатора). Таким образом, он сохраняет строку «abcd» в памяти, и мы можем получить доступ к этой строке, используя переменную new_str.

 char *new_str="abcd"; 

Это указывает, что строка abcd хранится где-то в памяти, а указатель new_str указывает на первый символ этой строки.

Чтобы дифференцировать их в стороне выделения памяти:

 // With char array, "hello" is allocated on stack char s[] = "hello"; // With char pointer, "hello" is stored in the read-only data segment in C++'s memory layout. char *s = "hello"; // To allocate a string on heap, malloc 6 bytes, due to a NUL byte in the end char *s = malloc(6); s = "hello"; 

Если вы в c ++, почему бы не использовать std :: string для всех ваших потребностей строки? Особенно все, что связано с конкатенацией. Это избавит вас от множества проблем.

  • Где в памяти строковые литералы? стек / куча?
  • Каковы операторы Pointer-to-Member -> * и. * В C ++?
  • Crash или «segmentation fault», когда данные копируются / отсканированы / прочитаны неинициализированному указателю
  • Не удается найти модуль 'angleular2 / angular2'
  • Как связаны iteratorы и указатели?
  • Возвращающий указатель от функции
  • Почему этот код segfault на 64-битной архитектуре, но отлично работает на 32-битной?
  • Как я могу индексировать массив MATLAB, возвращаемый функцией, не назначая сначала локальную переменную?
  • Функция для динамического выделения матрицы
  • Неинициализированные указатели в коде
  • Давайте будем гением компьютера.