2015-05-10 2 views
0

Я всегда интересно, в чем разница между этими двумя в Cуказателя на символ и массив символов в C

char *str; 
char str[50]; 

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

int read_line(char *str, int n); 

int main (int *argc, char *argv[]) 
{ 
    char *str; 

    read_line(str, 50); 
    printf("%s", str); 
    return 0; 
} 

int read_line(char *str, int n) 
{ 
    int ch, i = 0; 

    while((ch = getchar()) != '\n') 
    { 
    if(i < n) 
    { 
     *str++ = ch; 
     i++; 
    } 
} 
*str = '\0'; 

return i; 
} 

Сборник работает нормально, как ожидалось, но разбился, когда я попытался запустить. И затем я изменяю аргумент функции read_line(), вместо char *str Я использую char str[50].

Программа работает как ожидалось при использовании char *str[50] в качестве аргумента.

Может кто-нибудь объяснить, почему это происходит? или в чем основное отличие от pointer to char и character array?

+4

возможный дубликат [Какая разница между голец s \ [\] и символ \ * s в C? ] (http://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s-in-c) – skrrgwasme

+0

Когда вы пишете 'char * str;' у вас есть только указатель, нет массива. Но в случае 'char str [50];' у вас есть указатель char str, и у вас есть массив из 50 символов. В этом случае указатель инициализируется адресом первого элемента массива. – watou

+0

Прочтите раздел 6 [comp.lang.c FAQ] (http://www.c-faq.com/). –

ответ

1

Основное различие заключается в том, что позднее выделяется память для 50 символов (str - это указатель на первый элемент), в то время как первый просто объявляет указатель (кроме памяти не выделяется память, кроме самой переменной указателя).

+6

Нет, данный 'char str [50];', 'str' не является указателем. 'str' - это массив. В качестве выражения имя массива неявно преобразуется в указатель в большинстве, но не во всех контекстах. –

2

Идентификаторы массива более или менее работают как указатели.

Но с указателями вы всегда должны сделать 3 шага вручную:

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

char str[50]; делает все три, в то время как char *str; создает неинициализированный указатель, и вы даже не создаете буфер для указания.

Дальнейшие различия между указателями и массивами идентификаторами:

  • идентификатор массива представляет адрес массива в только время компиляции, в то время как указатель хранит адрес в памяти, и вы можете даже изменить его.
  • sizeof array возвращает размер массива, в то время как sizeof ptr возвращает размер памяти, необходимый для хранения адреса.
1

Разница будет видно сразу, если вы будете запускать эту простую программу

#include <stdio.h> 

int main(void) 
{ 
    char *str1; 
    char str2[50]; 

    printf("%zu\n", sizeof(str1)); 
    printf("%zu\n", sizeof(str2)); 
} 

Выход программы может выглядеть

4 
50 

Как вы видите массив str2 имеет достаточно памяти для хранить строку до 50 символов, в то время как указатель может хранить только адрес некоторой памяти.

Когда вы передаете массив в функцию, как в коде

read_line(str2, 50); 

(где str2 объявлен как char str2[50];), то имя массива неявно преобразуется в указатель на его первый элемент. Так, например, эти функции объявления эквивалентны

int read_line(char *str, int n); 
int read_line(char str[50], int n); 

или даже, как

int read_line(char str[100], int n); 
int read_line(char str[], int n); 

и объявить ту же одну функцию, так как параметр объявлен как массив настраивается на указатель.

Итак, когда вы передаете массив, функция получает указатель на первый элемент массива, для которого уже выделена память, потому что массив был определен.

Когда вы передаете указатель, как вы делали в этой основной функции

int main (int *argc, char *argv[]) 
{ 
    char *str; 

    read_line(str, 50); 
    printf("%s", str); 
    return 0; 
} 

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

Например, вы можете сделать это одним из следующих способов

int main (int *argc, char *argv[]) 
{ 
    char *str1; 
    char str2[50]; 

    str1 = str2; 

    read_line(str1, 50); 
    printf("%s", str1); 

    return 0; 
} 

или

int main (int *argc, char *argv[]) 
{ 
    char *str = malloc(50 * sizeof(char)); 

    read_line(str, 50); 
    printf("%s", str); 

    free(str); 

    return 0; 
}