¿Cual es la diferencia entre char name[] y char* name en C?

Alguien puede explicarme cual es la diferencia entre:

char* name = "Gerardo";

o

char name[] = "Gerardo";

Me gustaría saber las diferencias en términos de memoria o performance.

6
задан 12.09.2016, 10:04
3 ответа

Фундаментальное различие состоит в том, что в случае указателя записывается в один буквальная цепь символов. Пробовать изменять ее - неопределенное поведение.

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

Тот факт, что буквальный цепи не был изменяемым, позволь составителям делать некую оптимизацию. Если цепь повторена в коде и используется как буквальный составитель может использовать ту же копию цепи для всех использований, уменьшая использование памяти. Кроме того возможно использовать прямо, что быстрее.

Например, эта программа в C:

#include<stdio.h>
void f() {
  char* name = "Gerardo";
  puts(name);
}

int main(void) {
  char* name = "Gerardo";
  puts(name);
  return 0;
}

Код составленный сборщик (оставляя только значимые части):

.LC0:
        .string "Gerardo"     <----- Aparece solo una vez
        .section        .text.unlikely,"ax",@progbits

f:
.LFB23:
        .cfi_startproc
        movl    $.LC0, %edi <---- Ponemos la dirección de la cadena en edi
        jmp     puts        <---- Y puts usa la cadena desde ahí directamente
        .cfi_endproc

main:
.LFB24:
        .cfi_startproc
        subq    $8, %rsp
        .cfi_def_cfa_offset 16
        movl    $.LC0, %edi   <------- Main usa la misma cadena
        call    puts

Однако та же программа используя arrays:

void f() {
  char name[] = "Gerardo";
  puts(name);
}
int main(void) {
  char name[] = "Gerardo";
  puts(name);
  return 0;
}

Составив это:

f:
.LFB23:
        .cfi_startproc
        subq    $24, %rsp          <----- Hay que reservar espacio en la pila
        .cfi_def_cfa_offset 32     
        movq    %fs:40, %rax
        movq    %rax, 8(%rsp)
        xorl    %eax, %eax
        movq    %rsp, %rdi
        movabsq $31354164838819143, %rax <--- Hay que copiar la cadena a la pila;
                                         <--- Esto lleva tiempo y ocupa espacio
        movq    %rax, (%rsp)
        call    puts

main:
.LFB24:
        .cfi_startproc
        subq    $24, %rsp           <------ Reservando espacio en la pila
        .cfi_def_cfa_offset 32
        movq    %fs:40, %rax
        movq    %rax, 8(%rsp)
        xorl    %eax, %eax
        movq    %rsp, %rdi
        movabsq $31354164838819143, %rax  <--- Gerardo está 2 veces en el binario
        movq    %rax, (%rsp)
        call    puts

Чтобы составлять эти примеры я использовал gcc -c -S -O2 fichero.c (версия 5.4.0)

Заключение. Если ты не будешь изменять цепь, он быстрее и тратит меньше памяти альтернатива буквального цепи, распределенного указателю. Если ты будешь изменять цепь, ты должен использовать array.

7
ответ дан 03.12.2019, 20:27

Указатели символа используются для того, чтобы соглашаться обычно на цепи символов, так как эти construídas принимая как базовую адрес (адрес первого символа) и закладку конца цепи (символ '\0'). Заявление указателя характера продолжает обычные правила:

char * puntero_caracter;

Указатели цепей: Определение, Заявление и Начало. Заявление цепи может иметь следующую форму:

char cadena[LONGITUD];

Так размещает место для цепи ДЛИНЫ символы.

В C, имя монопространственных списков равняется адресу первого элемента тех же самых. Как только он решается места, размещенного для цепи, возможно строить указатель цепи используя следующие решения:

char * p;
char cadena[LONGITUD];
p = cadena;/* Esto equivale, desde luego, a poner: */
p = &cadena[0];

Ref.

http://maxus.fis.usal.es/fichas_c.web/07xx_PAGS/0702.html

3
ответ дан 24.11.2019, 13:27

Указатели в char соглашаются на цепи символов с адресом 1er элемент цепи, эта цепь заканчивается с '\0' (символ конца цепи). Когда ты делаешь ++ он продвигается в следующий адрес цепи (следующий символ).

Договоренности char - суфлер в 1er символ цепи. Следовательно, с точки зрения, поскольку они хранятся в памяти, нет различия. Это различие в синтаксисе, и там использовать синтаксис тип договоренность лучше, потому что, использовав синтаксис указателя, составитель должен решать перегрузку оператора * так как он также используется для умножения и это затрагивает немного результат в выполнении и компиляции.

Кроме того использовать договоренности - проще для человеческого глаза. Синтаксис понятнее с договоренностями чем с указателями.

2
ответ дан 24.11.2019, 13:27