2014-09-03 4 views
2

Я читал так много тем и вопросов об этом и читал так много ответов, но STILL испытывал трудности с пониманием различий и когда вы должны использовать что?Разница между char * и char []

Я думаю, вы должны использовать char *, когда вам нужно хранить данные, и вы не знаете его размер, потому что он динамический. Также я не уверен, что я прав, но из того, что я понял, если вы объявляете символ char * и присваиваете ему буквальный текст следующим образом: char * ch = "hi"; Это константа, которую вы не можете изменить, и если вы попытаетесь ее изменить, вы просто укажете ch на другое выделенное пространство памяти, содержащее новую строку? Если написать так: char ch = malloc (20); , то вы можете изменить значение , и если вы сделаете так: char ch [] = "hi"; char pch = ch; вы можете изменить значения, так как вы указываете на массив, а массивы указывают на ch [0]?

Все, что написано жирным шрифтом, является моим пониманием от чтения, хотя я, вероятно, ошибаюсь в отношении большинства вещей, которые я только что сказал, и именно поэтому мне нужно ДЕЙСТВИТЕЛЬНО ХОРОШЕЕ и простое объяснение, чтобы я мог раз и навсегда понять различия и когда я должен что-то использовать.

EDIT:

#include <stdio.h> 

main() 
{ 
    char ch[] = "Hello"; 
    char *p1 = ch; 
    char *p2 = p1; 
    char *p3 = *p1; 
    printf("ch : %s\n", ch); 
    printf("p1 address [%d] value is %s\n", p1, *p1); 
    printf("p2 address [%d] value is %s\n", p2, *p2); 
    printf("p3 address [%d] value is %s\n", p3, *p3); 
    return 0; 
} 
+0

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

ответ

13

Самый простой ответ:

Разница здесь в том, что

char *s = "Hello world"; 

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

char s[] = "Hello world"; 

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

s[0] = 'J'; 

юридический.

Более длинное объяснение будет включать в себя какие сегменты памяти хранится в и сколько памяти выделяется:

Example:      Allocation Type:  Read/Write: Storage Location: Memory Used (Bytes): 
=========================================================================================================== 
const char* str = "Stack";  Static    Read-only  Code segment  6 (5 chars plus '\0') 
char* str = "Stack";   Static    Read-only  Code segment  6 (5 chars plus '\0') 
char* str = malloc(...);  Dynamic    Read-write  Heap    Amount passed to malloc 
char str[] = "Stack";   Static    Read-write  Stack    6 (5 chars plus '\0') 
char strGlobal[10] = "Global"; Static    Read-write  Data Segment (R/W) 10 

Ссылки


  1. Что такое разница между char s [] и char * s в C?, Accessed 2014-09-03, <https://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s-in-c>
  2. Разница между заявленной строкой и выделенной строки, Accessed 2014-09-03, <https://stackoverflow.com/questions/16021454/difference-between-declared-string-and-allocated-string>

Редактировать


Для решения этой редактирование в вопросе и комментарий, выпущенный вместе с ним, я добавил примечания к вашему решению:

#include <stdio.h> 

int main() { 
    char ch[] = "Hello"; /* OK; Creating an array of 6 bytes to store 
         * 'H', 'e', 'l', 'l', 'o', '\0' 
         */ 
    char *p1 = ch;  /* OK; Creating a pointer that points to the 
         * "Hello" string. 
         */ 
    char *p2 = p1;  /* OK; Creating a second pointer that also 
         * points to the "Hello" string. 
         */ 
    char *p3 = *p1;  /* BAD; You are assigning an actual character 
         * (*p1) to a pointer-to-char variable (p3); 
         * It might be more intuitive if written in 
         * 2 lines: 
         * char* p3; 
         * p3 = *p1; //BAD 
         */ 
    printf("ch : %s\n", ch); /* OK */ 
    printf("p1 address [%d] value is %s\n", p1, *p1); /* Bad format specifiers */ 
    printf("p2 address [%d] value is %s\n", p2, *p2); /* Bad format specifiers */ 
    printf("p3 address [%d] value is %s\n", p3, *p3); /* Bad format specifiers */ 
    return 0; 
} 

Итак, три основных ошибки.

  1. Вы присваиваете char значение в pointer-to-char переменной. Ваш компилятор должен предупредить вас об этом. (char *p3 = *p1).
  2. В зависимости от вашего компилятора вам может понадобиться использовать указатель формата %p для печати адреса, а не спецификатор формата %d (целочисленный).
  3. Вы используете строку спецификатора %s с типом данных char (то есть: printf("%s", 'c') неверен). Если вы печатаете один символ, вы используете спецификатор формата %c, а соответствующий аргумент должен быть символом (например: 'c', char b и т. Д.). Если вы печатаете целую строку, вы используете спецификатор формата %s, а аргумент - указатель на символ.

Примеры


#include <stdio.h> 

int main(void) { 
    char c = 'H';     // A character 
    char* pC = &c;     // A pointer to a single character; IS NOT A STRING 
    char cArray[] = { 'H', 'e', 'l', 'l', 'o' }; // An array of characters; IS NOT A STRING 
    char cString[] = { 'H', 'e', 'l', 'l', 'o', '\0' }; // An array of characters with a trailing NULL charcter; THIS IS A C-STYLE STRING 
    // You could also replace the '\0' with 0 or NULL, ie: 
    //char cString[] = { 'H', 'e', 'l', 'l', 'o', (char)0 }; 
    //char cString[] = { 'H', 'e', 'l', 'l', 'o', NULL }; 
    const char* myString = "Hello world!"; // A C-style string; the '\0' is added automatically for you 

    printf("%s\n", myString);  // OK; Prints a string stored in a variable 
    printf("%s\n", "Ducks rock!"); // OK; Prints a string LITERAL; Notice the use of DOUBLE quotes, " " 
    printf("%s\n", cString);   // OK; Prints a string stored in a variable 

    printf("%c\n", c);    // OK; Prints a character 
    printf("%c\n", *pC);    // OK; Prints a character stored in the location that pC points to 
    printf("%c\n", 'J');    // OK; Prints a character LITERAL; Notice the use of SINGLE quotes, ' ' 

    /* The following are wrong, and your compiler should be spitting out warnings or even not allowing the 
    * code to compile. They will almost certainly cause a segmentation fault. Uncomment them if you 
    * want to see for yourself by removing the "#if 0" and "#endif" statements. 
    */ 
#if 0 
    printf("%s\n", c);    // WRONG; Is attempting to print a character as a string, similar 
            // to what you are doing. 
    printf("%s\n", *pC);    // WRONG; Is attempting to print a character as a string. This is 
            // EXACTLY what you are doing. 
    printf("%s\n", cArray);   // WRONG; cArray is a character ARRAY, not a C-style string, which is just 
            // a character array with the '\0' character at the end; printf 
            // will continue printing whatever follows the end of the string (ie: 
            // random memory, junk, etc) until it encounters a zero stored in memory. 
#endif 
    return 0; 
} 

Листинг - Предлагаемое решение


#include <stdio.h> 

int main() { 
    char ch[] = "Hello"; /* OK; Creating an array of 6 bytes to store 
         * 'H', 'e', 'l', 'l', 'o', '\0' 
         */ 
    char *p1 = ch;  /* OK; Creating a pointer that points to the 
         * "Hello" string. 
         */ 
    char *p2 = p1;  /* OK; Creating a second pointer that also 
         * points to the "Hello" string. 
         */ 
    char *p3 = p1;  /* OK; Assigning a pointer-to-char to a 
         * pointer-to-char variables. 
         */ 
    printf("ch : %s\n", ch); /* OK */ 
    printf("p1 address [%p] value is %s\n", p1, p1); /* Fixed format specifiers */ 
    printf("p2 address [%p] value is %s\n", p2, p2); /* Fixed format specifiers */ 
    printf("p3 address [%p] value is %s\n", p3, p3); /* Fixed format specifiers */ 
    return 0; 
} 

Пример вывода


ch : Hello 
p1 address [0x7fff58e45666] value is Hello 
p2 address [0x7fff58e45666] value is Hello 
p3 address [0x7fff58e45666] value is Hello 
+2

Какова цель стенографического копирования из дубликата? –

+1

@ OliCharlesworth OP отметил, что он уже просматривал существующие ответы, поэтому я взял особенно хороший и подробно рассмотрел его с слегка касательным ответом. Источники также цитировались. – DevNull

+1

@Dogbert Я попытался сделать некоторые тесты и сделал тестовую программу, и она сработает, можете ли вы указать мне, почему? Я отредактировал мой оригинальный пост – AALC

Смежные вопросы