Подтвердить что ты не робот

Что делает char * массив символов?

Обычно, если вы делаете следующее:

int * i = &someint;

Это просто указатель на переменную.

Но, когда вы делаете

char * str = "somestring";

он автоматически превращает его в массив. Является ли это указателем, который это делает, или это просто синтаксический сахар для синтаксиса инициализации?

4b9b3361

Ответ 1

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

Что делает этот оператор, установите str, чтобы указать на первый символ. Если бы вы посмотрели базовый код ассемблера, это выглядело бы так:

str314159:  db   "somestring", 0  ; all string literals here.
: :         : :
            load r0, str314159    ; get address of string
            stor r0, -24[sp]      ; store it into local var str.

В большом количестве случаев массив будет распадаться на указатель на первый элемент этого массива (с некоторыми ограниченными исключениями, например при выполнении sizeof).


В качестве примера, следующий код C:

#include <stdio.h>

int main (void) {
    char *somestr = "Hello";
    puts (somestr);
    return 0;
}

когда скомпилировано с gcc -S для сборки x86, дает нам (с нерелевантным отрывом):

.LC0:
    .string    "Hello"
    .text
.globl main
    .type      main, @function
main:
    pushl      %ebp                ; Standard set up of stack frame,
    movl       %esp, %ebp          ;   aligning and making
    andl       $-16, %esp          ;   room for
    subl       $32, %esp           ;   local variables.

    movl       $.LC0, 28(%esp)     ; Load address of string in to somestr.

    movl       28(%esp), %eax      ; Call puts with that variable.
    movl       %eax, (%esp)
    call       puts

    movl       $0, %eax            ; Set return code.

    leave                          ; Tear down stack frame and return.
    ret

Вы можете видеть, что адрес первого символа .LC0 действительно загружен в переменную somestr. И, хотя это может быть не сразу очевидно, .string создает массив символов, заканчивающихся символом NUL.

Ответ 2

Это не указатель на переменную. Это указатель на место в памяти. Вы создаете переменную и сохраняете ее в некоторой ячейке памяти, а затем указываете указатель в этом месте. Причина, по которой он работает для массивов, состоит в том, что элементы массива сохраняются обратно в память. Указатель указывает на начало массива.

Ответ 3

char * str 

- указатель на символ. Когда вы назначаете строку указателю на символ, она указывает на первый символ строки, а не на всю строку. Если указатель увеличивается, вы можете видеть, что он указывает на второй символ в строке. Когда вы печатаете указатель на символ, объект cout печатает символ и продолжает печатать символ до появления нулевого символа (\ 0).

#include <iostream>
using namespace std;

int main()
{
    char *s = "something";
    cout << "before :" << s << endl;
    s++;
    cout << "after :" << s << endl;
}

Эта программа печатает:

~/cpp: ./stringarray
before :something
after :omething

Ответ 4

int * i = &someint;

В дополнение к другим комментариям. Как правило, мы можем сказать, что это указатель на расположение размера (int). Итак, когда мы получаем доступ к значению внутри "i". т.е. * i, извлекается ячейка памяти sizeof (int). Кроме того, арифметический расчет выполняется таким же образом. То есть, увеличивая указатель я + 1, увеличивается + sizeof (int). Следовательно, размер полученных данных зависит от типа данных переменной.

Ответ 5

Слово, которое вы используете "обычно", является большой частью проблемы здесь.

Я думаю, что часть того, что может сбить с толку, - это многие функции, которые принимают char *, ищут строку стиля c (т.е. нулевой конец символьного массива). То, что они хотят. Вы можете написать функцию, которая просто смотрела на персонажа.

Аналогичным образом вы могли бы написать функцию, которая взяла int * и обработала ее как нуль-завершенный массив, но это просто не так. И не зря, потому что, если вам нужно значение 0? в строках стиля c (для отображения не двоичных данных) вам никогда не понадобится 0.

#include <iostream>

const int b_in_data[]={50,60,70,80,0};

int Display (const int * a)
{
  while ( *a != 0){
    std::cout << *a; ++a;
  }
}    

int main()
{

 int a[]={20,30,40,0};

 // or more like char* = something because compiler is making string literal for you 
 // probably somewhere in data section and replacing it with its address
 const int *b = b_in_data;

 Display(a);
 Display(b);
 return 0;
}

Строки стиля C просто решили закончить, а не передавать размер, тогда строки стиля B передали размер. массивы ints обычно не являются нулевыми, но могут быть. Доходит до "обычно".

Ответ 6

Как говорили люди, str - это не массив, а только указатель на char (первый из "что-то", поэтому s). Однако есть 2 синтаксиса сахара

1- "something" инициализируйте блок памяти всеми символами ** и добавьте \0 в конец. Итак,

char *str = "something";

- синтаксический сахар для

char *str = {'s', 'o', 'm', 'e', 't', 'h', 'i', 'n', 'g', '\0'};
              ^                                          ^^^^^
              |
              +- str

Так технически str, это 10 символов, а не 9. (Обратите внимание, что str указывает только на

2 -

str[5] 

- синтаксический сахар для

*(str + 5)      

Тогда существует соглашение о том, что большинство (не все) C-функции, связанные со строками, ожидают, что последний символ \0 (знать, где он заканчивается). Некоторые другие (см. strncpy, нужны длина в качестве дополнительного аргумента и могут добавлять или не "\ 0".