можно ли изменить переменную const char *?
Указывает только, что ch указывает на const . Он не говорит, что ch сам это const .
Что ch инициализируется, так это адрес строкового литерала, а строковые литералы доступны только для чтения. Когда вы сделаете это:
Вы назначаете ch адрес другого строкового литерала. Итак, что вы делаете, четко определено.
Если бы вы пытались это сделать:
Вы получите ошибку компилятора, потому что пытаетесь изменить что-то, что является const . Если бы вы оставили квалификатор const и сделали это, ваш код, скорее всего, вылетел бы из-за того, что вы пытаетесь изменить строковый литерал, доступный только для чтения.
Давайте разложим ваш код на следующий, чтобы лучше понять, что вы делаете:
Еще вам необходимо знать, что любая жестко закодированная строка хранится в памяти, и когда вы используете ее в выражении C, они получают значение указателя на первый символ в строке. Вот почему ваш код будет работать безупречно, и в этом случае не будет никаких переполнений , даже если длина второй строки составляет 20 миллионов символов.
Я поясню это на примере. Если при выполнении программы строка «текст» загружается в память по адресу 0x0100, а «Длинный текст» загружается по адресу 0x0105 (они являются смежными), то после выполнения ch = «text» ch будет иметь значение 0x0100 , а после выполнения ch = «long text» ch будет иметь значение 0x0105. В этом случае обе строки выделяются в памяти, вы не пишете в памяти.
Я иду на ОТ, потому что я прочитал ваш комментарий к вашему вопросу, когда писал этот ответ. Пожалуйста, не обращайтесь с указателями как с массивами. Указатель — это переменная, которая содержит (логический) адрес памяти, тогда как массив — это нечто иное. Однако я понимаю путаницу, потому что массивы в C, когда используются внутри выражений, они получают значение указателя на свои первые элементы.
Позвольте мне пояснить лучше: вы можете иметь статический массив в C (скажем, из int ), просто написав int arr[10] (где вместо 10 вы можете написать любое fixed номер вы хотите). arr — это массив, но всякий раз, когда он используется внутри выражения, такого как arr[5] = 123 , arr преобразуется в указатель на первый элемент массива arr (то есть <
Ни больше ни меньше.
Хорошо, давайте вернемся в нужное русло. Если у вас был динамический массив, который представляет собой логически непрерывное пространство в памяти, размер которого в вашей программе фиксирован в любой момент времени (я имею в виду, что размер может измениться, если вы явно укажете это), и вы скопировали строки в это пространство памяти, тогда вы были бы правы. Если бы вы сделали следующее, то были бы правы:
Но не со следующим кодом:
Обратите внимание, что в последних двух частях кода я скопировал и вставил исходный код, где массив был размещен в стеке, а не динамически размещен в куче, однако в первом фрагменте кода str представляет собой массив а в последних двух частях это указатель. Также обратите внимание, что значение указателя не имеет ничего общего с содержимым памяти по этому адресу. Итак, если вы это сделали:
Он будет работать без переполнения. Это потому, что единственное, что вы сделали, — это заменили значение указателя, хранящегося в переменной str , на значение указателя, хранящегося в mystr2 : это разные части памяти!
C ++ изменить значение в const char
и я хочу изменить последние 4 байта примера1 с примерами на примере2, что я могу сделать в C++?
я пробовал memcpy , strcpy и strcpy_s без везения
5 ответов
- Donot изменить постоянную строку.
- const char example[] = «\x4D\x5A\xE8\x00\x00\x00\x00\x5B\x52\x45\x55\x89\xE5\x81\xC3»; здесь ваша строка содержит несколько NULL-ограничителей строк. Это НЕ будет работать с функциями в <string.h> (например, strlen() и другими)
- Вместо этого используйте функции memcpy , memset чтобы добавить ТОЛЬКО после знания длины двоичной строки.
- Сохраните результат в массиве символов, но не предполагайте, что он будет работать как обычная строка из-за ваших данных.
Вы не должны изменять постоянный массив!
Изменение неотъемлемо постоянного объекта/переменной приводит к неопределенному поведению.
Только не делай этого. Сделайте копию и измените эту копию, или если вы хотите изменить тот же массив, просто не объявляйте его как const .
ваш example[] char array определяется как const поэтому вы не можете его изменять.
1) Вы должны получить eror в компиляции, если вы измените массив const char таким образом
2) Вы должны получить предупреждение, если вы измените свой массив const char через memcpy или через strcpy
Измените его на
И вы не можете использовать strcpy потому что ваш массив символов содержит x00 посередине, поэтому это повлияет на функцию strcpy . Поскольку strcpy останавливается, когда находит x00 в массиве char
example[] char array содержит x00 посередине, поэтому, чтобы найти длину example[] strlen не будет работать должным образом. В этом случае я предлагаю вместо этого использовать sizeof(example) .
Здесь, после того как вы можете сделать свою копию:
Вы никогда не должны изменять константу, включая постоянный массив. Если вы хотите, чтобы изменить то, что у вас есть выше, создайте копию и изменить копию. Как указано RasmusKaj strcpy, вам не поможет, поскольку исходные строки содержат нулевые символы, поэтому, возможно, используйте memcpy для создания копии.
Константные переменные не могут быть изменены. Это по дизайну. В случае строки ac вы можете иметь содержимое строки const или указатель на строку const.
Поскольку вы определяете его как массив константных символов, указатель неявно const и содержимое явно const.
В этом случае первая «константа» пытается применить левую (нет ничего), поэтому она применяется правильно (к типу char). Поэтому содержимое строки может не измениться. Второй const пытается применить левый, поэтому он делает сам указатель const. Это означает, что указатель на мишень должен всегда указывать на то, где «h» от «привет» в памяти.
Поэтому, если я попробую:
Они не сработают. Если вы удалили первый или второй const соответственно, их можно было бы заставить работать.
Цель const позволяет вам сказать заранее: «эту переменную нельзя изменить». Это означает, что если он изменен, возникает проблема. Как правило, вы всегда должны использовать const с любой переменной, которую вы не хотите изменять после создания экземпляра.
Почему я могу изменить значение переменной const char *?
Поскольку str является указателем на постоянный символ, почему нам разрешено назначать ему разные строковые литералы? Далее, как мы можем защитить str от модификации? Кажется, что это может быть проблемой, если, например, мы позже присвоим str более длинной строке, которая в конечном итоге запишет другую часть памяти.
Я должен добавить, что в своем тесте я распечатывал адрес памяти str до и после каждого из моих назначений, и он никогда не менялся. Таким образом, несмотря на то, что str является указателем на const char, на самом деле память модифицируется. Я задавался вопросом, возможно, это устаревшая проблема с C?
Я предполагаю, что вы на самом деле распечатывали адрес переменной str, которая не меняется, меняется ее значение. — Greg Rogers
6 ответы
Вы меняете указатель, который не является константой (то, на что он указывает, является константой).
Если вы хотите, чтобы сам указатель был константным, объявление будет выглядеть так:
Константные указатели на неконстантные данные обычно менее полезны, чем указатели на константы.
Однако я сделал тест. Я присвоил str строке и распечатал строку и ее адрес памяти. Затем я присвоил str другой строке и снова распечатал строку и ее адрес в памяти. Строковый литерал изменился, но адрес не изменился. — Крис
Вы распечатали адрес указателя или адрес, на который указывает указатель? — мипади
Спасибо всем. Да, я распечатывал адрес указателя, а не данные! Что меня сбило с толку в этой проблеме, так это то, как C работает со строковыми литералами. Вы можете присвоить строковый литерал char*, но вы не можете, например, таким же образом присвоить целое число int*. — Крис
@Chris: это потому, что строковый литерал на самом деле является char [], который может быть неявно преобразован в указатель на его первый элемент — Кристоф
Why can I change the value of a const char* variable?
Since str is a pointer to a constant character, why are we allowed to assign it different string literals? Further, how can we protect str from being modified? It seems like this could be a problem if, for example, we later assigned str to a longer string which ended up writing over another portion of memory.
I should add that in my test, I printed out the memory address of str before and after each of my assignments and it never changed. So, although str is a pointer to a const char, the memory is actually being modified. I wondered if perhaps this is a legacy issue with C?