Почему const char * не нужен указатель на адрес памяти? - PullRequest
18 голосов
/ 18 апреля 2020

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

Пример:

const char* a = "Anthony";

, а не:

const char *a = // Address to const char

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

Ответы [ 4 ]

26 голосов
/ 18 апреля 2020

Вы можете представить это объявление

const char* a = "Anthony";

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

const char string_literal[] = "Anthony";

const char *a = string_literal;

То есть компилятор создает массив символов со статикой c длительности хранения, в котором хранится строка "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 голосов
/ 18 апреля 2020

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

.

A C Строковый литерал, такой как

"Anthony"

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

1 голос
/ 19 апреля 2020

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

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

0 голосов
/ 18 апреля 2020

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

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

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

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

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

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

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

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

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

...