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

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

char new_str[]="";

char * newstr;

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

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

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

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

Ответ 1

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

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

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

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

Ответ 2

Отличным источником для устранения путаницы является Питер Ван дер Линден, программирование экспертов 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;
OR
*(new_str + 1) = newstr[1];

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

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

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

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.

Ответ 6

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

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

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

char new_str[] = "";

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

char *new_str = "";

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

char *new_str;

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

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

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

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

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

Ответ 7

char new_str[]="abcd";  

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

char *new_str="abcd";  

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

Ответ 8

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

// 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++ 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";

Ответ 9

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