Почему const char * не нужен указатель на адрес памяти?

18

Это может быть простой вопрос, но почему const char * не нужен адрес памяти для указания?

Пример:

const char* a = "Anthony";

и не:

const char *a = // Address to const char

как и любые другие типы делают?

Weidelix
источник
8
Что заставляет вас думать, что строковые литералы не имеют адресов памяти?
user207421
2
Согласовано. Я бы не ожидал, что кто-нибудь, задавая этот вопрос, узнает, что существуют категории ценностей , не говоря уже о том, что у них есть имена.
user4581301
13
Пожалуйста, не задавайте вопросов с тегами C и C ++. Как мы можем видеть, ответы теперь специфичны для C ++, и комментарии снова обманывают различия между обоими языками. Сейчас существует так много различий, что трудно задать вопрос, который на самом деле имеет одинаковый действительный ответ для обоих языков. Решите, какой язык вы хотите использовать, прежде чем спрашивать, пожалуйста.
Ларки

Ответы:

26

Вы можете представить эту декларацию

const char* a = "Anthony";

следующим образом

const char string_literal[] = "Anthony";

const char *a = string_literal;

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

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

#include <iostream>
#include <type_traits>

decltype( auto ) f()
{
    return ( "Anthony" );
}

template <size_t N>
void g( const char ( &s )[N] )
{
    std::cout << s << '\n';
}

int main() 
{
    decltype( auto ) r = f();

    std::cout << "The size of the referenced array is "
              << std::extent<std::remove_reference<decltype( r )>::type>::value
              << '\n';

    g( r );

    return 0;
}

Выход программы

The size of the referenced array is 8
Anthony

Размер строкового литерала (массива, в котором хранится строковый литерал) равен тому, 8что строка также содержит символ завершающего нуля ' \0'.

В демонстрационной программе выражение

std::extent<std::remove_reference<decltype( r )>::type>::value

может быть заменено только выражение

sizeof( r )
Влад из Москвы
источник
5

почему const char не нужен адрес памяти для указания? *

Оно делает.

C-строка буквального типа

"Anthony"

распадается по адресу 1- го символа. Как, кстати; любой массив в C делает.

алк
источник
Более конкретно, он имеет тип const char[8](в C ++, может быть char [8]в C, не уверен) и, как и все встроенные массивы, при использовании его в качестве значения он распадается на указатель на свой первый элемент.
Никос С.
@NikosC .: Спасибо, что напомнили мне о самом важном магическом глаголе в этом контексте! ;)
алк
Спасибо за ответ! Мне было интересно, откуда он взял память.
Weidelix
1
Не могу говорить за C, но я уверен, что C ++ не указывает, где должен храниться строковый литерал. Просто пошел копать. Если есть правило, оно похоронено где-то странно и далеко от любого упоминания о «строковом литерале».
user4581301
2
@NikosC. char [8]в C: c-faq.com/ansi/strlitnotconst.html
Дэвид Раньери
1

Ему нужен адрес памяти, и он имеет адрес памяти. В вашем примере это просто адрес памяти начала строки. То же самое с любой другой переменной массива, которая инициализируется во время компиляции, например, "int array [] = {0, 1, 2, 3};".

Если бы вы использовали бинарный редактор для просмотра исполняемого файла, вы бы увидели там строку «Энтони». Если вы поставите строку "printf (" a находится в% p \ n ", (void *) a);" в вашей программе, затем скомпилируйте и запустите ее, вы увидите адрес.

jamesqf
источник
0

«Почему const char*не нужен указатель на адрес памяти?»

На самом деле, ему нужен адрес памяти, на который можно указать.

const char* aозначает aуказатель на строковый литерал или символьную константу.

Для указателя всегда требуется адрес, на который указывает указатель, поскольку указатель указывается на конкретный объект в памяти. Так что, aи любой другой указатель на const charтоже.

Строковый литерал, подобный "Hi My Name is Alfred!"присваиванию, например:

const char* a;
a = "Hi My Name is Alfred!";

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

Значит, в свою очередь, aприсваивается по адресу первого элемента строкового литерала, "Hi My Name is Alfred!"который может храниться где угодно в памяти, в зависимости от среды выполнения.

Не в силах программиста точно хранить строковый литерал. Ваше назначение - только назначать и обрабатывать соответствующий указатель соответствующим образом.

RobertS поддерживает Монику Челлио
источник