Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c语言中的字符串指针和字符数组_C_String_Pointers_Compiler Errors - Fatal编程技术网

c语言中的字符串指针和字符数组

c语言中的字符串指针和字符数组,c,string,pointers,compiler-errors,C,String,Pointers,Compiler Errors,我刚开始学习C,发现一些关于字符串指针和字符串(字符数组)的混淆。谁能帮我清醒一下头脑吗 // source code char name[10] = "Apple"; char *name2 = "Orange"; printf("the address of name: %p\n", name); printf("the address of the first letter of name: %p\n", &(*name)); printf("first letter of na

我刚开始学习C,发现一些关于字符串指针和字符串(字符数组)的混淆。谁能帮我清醒一下头脑吗

// source code
char name[10] = "Apple";
char *name2 = "Orange";

printf("the address of name: %p\n", name);
printf("the address of the first letter of name: %p\n", &(*name));
printf("first letter of name using pointer way: %c\n", *name);
printf("first letter of name using array way: %c\n", name[0]);
printf("---------------------------------------------\n");
printf("the address of name2: %p\n", name2);
printf("the address of the first letter of name2: %p\n", &(*name2));
printf("first letter of name2 using pointer way: %c\n", *name2);
printf("first letter of name2 using array way: %c\n", name2[0]);

// output
the address of name: 0x7fff1ee0ad50
the address of the first letter of name: 0x7fff1ee0ad50
first letter of name using pointer way: A
first letter of name using array way: A
---------------------------------------------
the address of name2: 0x4007b8
the address of the first letter of name2: 0x4007b8
first letter of name2 using pointer way: O
first letter of name2 using array way: O
所以我假设name和name2都指向他们自己的第一个字母的地址。那么我的困惑是(见下面的代码)

我创建了一个名为name2的char指针,name2指针指向“Apple”的第一个字母,这很好,然后我创建了另一个char数组,并在内存中分配了10个空间。然后尝试使用name4,它是指向“Apple”的第一个字母的地址。结果,我得到了一个编译错误

我对这种编程语言非常失望。有时它们的工作原理是一样的。但有时他们不会。有人能解释一下原因吗?如果我真的想在分隔行中创建字符串或字符数组。我怎么能做到呢


非常感谢…

您不能直接将值重新分配给数组类型(例如,您的十字符数组
char
s
name4
)。对于编译器来说,
name4
是一个“数组”,您不能使用赋值
=
运算符来使用字符串文本写入数组

为了将字符串“Apple”的内容实际移动到分配给它的十字节数组中(
name4
),必须使用
strcpy()
或类似的东西

您使用的
name3
是完全不同的。它被创建为一个
char*
,并初始化为垃圾或零(此时您还不能确定)。然后,将静态字符串“Apple”的位置指定给它。这是一个位于只读内存中的字符串,尝试写入
name3
指针指向的内存永远不会成功

基于此,您可以推测最后一条语句试图将静态字符串的内存位置分配给表示10
char
s集合的其他地方。该语言不为您提供执行此任务的预定义方式

这就是它的力量所在

当你说

char *name3 = "Apple";
char name4[10];
name4 = "Apple";
您正在声明
name3
以指向静态字符串
“Apple”
。如果您熟悉高级语言,可以将其视为不可变的(我将在本文中对此进行解释,因为它听起来像您以前编程过;关于技术原理,请查看C标准)

当你说

char *name3 = "Apple";
char name4[10];
name4 = "Apple";
出现错误是因为您首先声明了一个包含10个字符的数组(换句话说,“指向”可变内存的10字节部分的开头),然后尝试将不可变值
“Apple”
分配给该数组。在后一种情况下,实际的数据分配发生在内存的某个只读段中

这意味着类型不匹配:

error: incompatible types when assigning to type 'char[10]' from type 'char *'
如果希望
name4
具有值
“Apple”
,请使用
strcpy

strcpy(name4, "Apple");
c[3] = 'e';       // Now c = "date", or 'd', 'a', 't', 'e', '\0'
strcpy(c, "hi");  // Now c = 'h', 'i', '\0', 'e', '\0'
strcpy(c, "too long!") // Error: overflows into memory we don't own.

如果希望
name4
具有初始值
“Apple”
,也可以这样做:

char name4[10] = "Apple"; // shorthand for {'A', 'p', 'p', 'l', 'e', '\0'}
这是因为
“Apple”
char[]
的有效数组初始化器。换句话说,您正在创建一个10字节的字符数组,并将其初始值设置为
“Apple”
(剩余位置为0)

如果考虑int数组,这可能更有意义:

int array[3] = {1, 2, 3}; // initialise array

可能我能想到的最简单的口语解释是数组是事物的bucket集合,而静态字符串
“Apple”
是“那边”的单个事物

strcpy(name4,“Apple”)
可以工作,因为它将
“Apple”
中的每个东西(字符)逐个复制到
name4


然而,说“这个桶集合等于那边的那个东西”是没有意义的。用值“填充”存储桶才有意义。

尽管指针和数组看起来很熟悉,但它们是不同的。
char*name3
只是一个指向
char
的指针,它只占用一个指针的内存。它只在其中存储一个地址,因此您可以为它分配一个字符串,然后将存储在
name3
中的地址更改为
“Apple”
的地址


但是你的
name4
是一个
char[10]
数组,它保存着10个char的内存,如果你想分配它,你需要使用
strcpy
或其他东西来写它的内存,但不要给它分配一个像
“Apple”
这样的地址,我想这也会有助于清除它:

int main() {
    char* ptr   = "Hello";
    char  arr[] = "Goodbye";

    // These both work, as expected:
    printf("%s\n", ptr);
    printf("%s\n", arr);
    printf("%s\n", &arr);   // also works!

    printf("ptr  = %p\n", ptr);
    printf("&ptr = %p\n", &ptr);
    printf("arr  = %p\n", arr);
    printf("&arr = %p\n", &arr);

    return 0;
 }
输出:

你好 再见 再见 ptr=0021578C &ptr=0042FE2C arr=0042FE1C\\相同! &arr=0042FE1C/ 所以我们看到,
arr==&arr
。由于它是一个数组,编译器知道您总是想要第一个字节的地址,不管它是如何使用的

arr
是一个7+1字节的数组,位于
main()
的堆栈上。编译器生成保留这些字节的指令,然后用“再见”填充它。没有指针


另一方面,
ptr
是一个指针,也是堆栈上的一个4字节整数。这就是为什么
&ptr
&arr
非常接近的原因。但它指向的是一个静态字符串(“Hello”),它在可执行文件的只读部分处于关闭状态(这就是为什么
ptr
的值是一个非常不同的数字)。

您可以在声明数组时初始化它,如下所示:

int n[5] = { 0, 1, 2, 3, 4 };
char c[5] = { 'd', 'a', 't', 'a', '\0' };
但由于我们通常将字符数组视为字符串,C允许一种特殊情况:

char c[5] = "data";  // Terminating null character is added.
但是,一旦声明了数组,就不能重新分配它。为什么?考虑一个类似

的任务
char *my_str = "foo";  // Declare and initialize a char pointer.
my_str = "bar";        // Change its value.
第一行声明了一个char指针,并将其“瞄准”在
foo
中的第一个字母。由于
foo
是一个字符串常量,它与所有其他常量一起驻留在内存中的某个位置。当您重新分配指针时,您将