Чому const char * не потребує вказівника на адресу пам'яті?


18

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

Приклад:

const char* a = "Anthony";

і ні:

const char *a = // Address to const char

як і будь-які інші типи?


8
Чому ви думаєте, що рядкові літерали не мають адреси пам'яті?
користувач207421

2
Домовились. Я б не очікував, що хтось, хто задає це питання, навіть знає, що існують цінні категорії , не кажучи вже про те, що вони мають імена.
користувач4581301

13
Будь ласка, не задавайте питань із тегами C та C ++. Як ми можемо спостерігати, відповіді зараз є специфікою C ++, і коментарі знову скасовують різницю між обома мовами. На сьогоднішній день існує стільки відмінностей, що важко задати питання, яке насправді має однакову правильну відповідь для обох мов. Визначте, якою мовою ви хочете скористатися, перш ніж запитувати, будь ласка.
larkey

Відповіді:


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 не потрібна адреса пам'яті, на яку слід вказувати? *

Це робить.

Буквал типу C-string

"Anthony"

загасає на адресу його 1 - го символу. Мовляв, BTW; будь-який масив в C робить.


Більш конкретно, він типу const char[8](в C ++, може бути char [8]в C, не впевнений) і, як і всі вбудовані масиви, коли він використовує його як значення, воно схиляється до вказівника на його перший елемент.
Нікос К.

@NikosC. Дякуємо, що нагадали мені про найважливіше магічне дієслово в цьому контексті! ;)
алк

Дякую за відповідь! Мені було цікаво, звідки воно бере пам’ять.
Weidelix

1
Не можу говорити для C, але я впевнений, що C ++ не вказує, де повинен зберігатися буквар жала. Просто пішов копати. Якщо є правило, він похований десь дивним і далеко від будь-якої згадки про "рядкові букви".
користувач4581301


1

Для цього потрібна адреса пам'яті, і вона має адресу пам'яті. У вашому прикладі це просто адреса пам'яті початку рядка. Це те ж саме з будь-якою іншою змінною масиву, ініціалізованою під час компіляції, наприклад, "int array [] = {0, 1, 2, 3};".

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


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!"який може зберігатися в будь-якому місці пам'яті, залежно від середовища виконання.

Це не в силах програміста, де точно зберігається літеральний рядок. Ваше завдання полягає лише в призначенні та обробці відповідного вказівника відповідним чином.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.