关于C#:char*和char[]的区别

The difference between char * and char[]

本问题已经有最佳答案,请猛点这里访问。

我读了很多关于它的文章和问题,读了很多答案,但仍然很难理解它们的区别,以及什么时候应该使用什么?

我认为需要存储数据时应该使用char*,因为它是动态的,所以您不知道它的大小。另外,我不确定我是否是对的,但根据我所了解的,如果您声明一个char*并为它指定如下文本:char*ch="嗨";它是一个常数,你不能改变它,如果你真的尝试改变它,你只需要把ch指向另一个分配的内存空间来保存新的字符串?如果这样写:char ch=malloc(20);然后您可以更改值如果你这样做:char ch[]="嗨";CHCH=CH;您也可以更改这些值,因为您指向数组,而数组指向ch[0]?

所有这些都是用粗体字写的,这是我从阅读中理解的,尽管我可能对我刚才说的大部分内容都是错的,这就是为什么我需要一个非常好和简单的解释,这样我就可以一次又一次地理解不同之处,以及什么时候应该使用什么。

编辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

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


最直接的答案是:

The difference here is that

1
char *s ="Hello world";

will place Hello world in the read-only parts of the memory and making
s a pointer to that, making any writing operation on this memory
illegal. While doing:

1
char s[] ="Hello world";

puts the literal string in read-only memory and copies the string to
newly allocated memory on the stack. Thus making

1
s[0] = 'J';

legal.

一个更冗长的解释将包括内存存储在哪个段,以及分配了多少内存:

1
2
3
4
5
6
7
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

工具书类

  • C中char s[]和char*s的区别是什么?,访问日期:2014-09-03,
  • 申报字符串与分配字符串的差异,访问日期:2014-09-03,
  • 编辑

    为了解决问题中的编辑和随问题一起发布的评论,我在您的解决方案中添加了注释:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    #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
    "
    , ch);   /* OK */
       printf("p1 address [%d] value is %s
    "
    , p1, *p1);  /* Bad format specifiers */
       printf("p2 address [%d] value is %s
    "
    , p2, *p2);  /* Bad format specifiers */
       printf("p3 address [%d] value is %s
    "
    , p3, *p3);  /* Bad format specifiers */
       return 0;
    }

    所以,三个主要的错误。

  • 您正在将char值分配给pointer-to-char变量。您的编译器应该警告您这一点。(char *p3 = *p1号)。
  • 根据编译器的不同,可能需要使用指针%p格式说明符来打印地址,而不是%d格式说明符。
  • 您使用的字符串%s说明符具有char数据类型(即:printf("%s", 'c')错误)。如果要打印单个字符,则使用%c格式说明符,匹配参数应为字符(即:"c"、char b等)。如果要打印整个字符串,则使用%s格式说明符,参数是指向char的指针。
  • 实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #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
    "
    , myString);        // OK; Prints a string stored in a variable
       printf("%s
    "
    ,"Ducks rock!");   // OK; Prints a string LITERAL; Notice the use of DOUBLE quotes,""
       printf("%s
    "
    , cString);         // OK; Prints a string stored in a variable

       printf("%c
    "
    , c);               // OK; Prints a character
       printf("%c
    "
    , *pC);             // OK; Prints a character stored in the location that pC points to
       printf("%c
    "
    , '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
    "
    , c);               // WRONG; Is attempting to print a character as a string, similar
                                        // to what you are doing.
       printf("%s
    "
    , *pC);             // WRONG; Is attempting to print a character as a string. This is
                                        // EXACTLY what you are doing.
       printf("%s
    "
    , 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;
    }

    代码列表-建议的解决方案

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #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
    "
    , ch);   /* OK */
       printf("p1 address [%p] value is %s
    "
    , p1, p1);  /* Fixed format specifiers */
       printf("p2 address [%p] value is %s
    "
    , p2, p2);  /* Fixed format specifiers */
       printf("p3 address [%p] value is %s
    "
    , p3, p3);  /* Fixed format specifiers */
       return 0;
    }

    样本输出

    1
    2
    3
    4
    ch : Hello
    p1 address [0x7fff58e45666] value is Hello
    p2 address [0x7fff58e45666] value is Hello
    p3 address [0x7fff58e45666] value is Hello