Два строковых литерала имеют одинаковое значение указателя?

Когда я запускаю эту программу, используя MinGW, я получаю вывод как «=»

#include<iostream>

using namespace std;

int main()
{
char *str1 = "Hello";
char *str2 = "Hello";

if(str1==str2)
cout<<"=";
else
cout<<"!=";return 0;
}

Однако, по логике, это должно быть! =, Потому что это указатели, и они указывают на разные области памяти. Когда я запускаю этот код в моем Turbo C ++, я получаю! =

8

Решение

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

14

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

Нет никаких гарантий, что два указателя указывают на разные области памяти. Может быть, это потому, что оптимизации или компилятор использует свои собственные правила … поведение «Реализация определена».

Согласно стандарту (C ++ 11 §2.14.5 Строковые литералы):

Все ли строковые литералы различны (то есть, сохранены
в неперекрывающихся объектах) определяется реализацией.

10

Это ожидаемый результат. Вы можете убедиться в этом, посмотрев на базовую сборку. Например, если я строю с:

g++ -S ptr.c

тогда вы можете увидеть следующее в выводе файла (ptr.s):

        .file   "ptr.c".def    ___main;        .scl    2;      .type   32;     .endef
.section .rdata,"dr"LC0:
.ascii "Hello\0"               ; Note - "Hello" only appears once in
; this data section!
LC1:
.ascii "=\0"LC2:
.ascii "!=\0".text
.globl _main
.def    _main;  .scl    2;      .type   32;     .endef
_main:
[... some stuff deleted for brevity ...]
LCFI5:
call    ___main
movl    $LC0, -12(%ebp)        ; This sets str1
movl    $LC0, -8(%ebp)         ; This sets str2
movl    -12(%ebp), %eax

Я прокомментировал два ключевых бита — только один вид «Hello» находится в разделе rdata основного кода, и вы можете видеть, что str1 и str2 установлены в конце, оба указывают на одну и ту же метку: LC0, Это потому, что «Hello» является строковым литералом и, что важно, постоянная.

Как уже отмечали другие — это совершенно законно по стандартам.

4

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

Стандарт C ++ дает компиляторам свободу объединять одинаковые постоянные значения (обратите внимание, что компиляторы не требуется сделать так).

Связанный: поэтому объявления являются недействительными и должны быть изменены на:

const char *str1 = "Hello";
const char *str2 = "Hello";

или если вы хотите

char const *str1 = "Hello";
char const *str2 = "Hello";

который хорошо читается при чтении справа налево:

str1 is a pointer to const char

.

2

char *str1 = "Hello"; — хотя эта строка разрешена (многими компиляторами), на самом деле это плохая идея. Это в основном разрешено только для обратной совместимости с C, а запись в * str1 приводит к неопределенному поведению. Я бы порекомендовал найти параметр компилятора, который выдает предупреждения, когда вы делаете это, и если вашему компилятору не хватает таких предупреждений при поиске нового компилятора.

Стандарт C ++ дает компиляторам и средам исполнения смехотворную свободу в отношении того, где "String literals" хранятся. Они могли буквально использовать указатель на "literal" часть "String literals" в качестве значения указателя для "literal"и сохранение их в памяти, в которой вы можете избежать ошибки при попытке их редактирования, не является неожиданным.

Обратите внимание, что char buf1[] = "Hello"; делает что-то принципиально другое, чем char* str1 = "Hello";: фактически инициализирует буфер buf1 с персонажами {'H','e','l','l','o','\0'},

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector