13

我正在阅读 Kernighan 和 Richie 的The C Programming Language中关于数组和指针的章节。

他们举了一个例子:

/* strlen:  return length of string s */
int strlen(char *s)
{
    int n;

    for (n = 0; *s != '\0'; s++)
        n++;
    return n;
}

然后说:

“既然s是指针,递增它是完全合法的;s++对调用的函数中的字符串没有影响strlen,而只是增加 strlen 的指针的私有副本。这意味着像

strlen("hello, world");  /* string constant */
strlen(array);           /* char array[100]; */
strlen(ptr);             /* char *ptr; */

一切正常。”</p>

除了第一个调用示例之外,我觉得我理解了所有这些:为什么或如何将字符串文字"hello, world"视为char *s? 这是一个怎样的指针?该函数是否将此字符串文字分配为其局部变量的值*s,然后s用作数组名称/指针?

4

6 回答 6

15

要理解像“Hello World”这样的字符串是如何转换为指针的,重要的是要理解,字符串实际上是十六进制数据,从一个地址开始移动直到找到一个NULL

这意味着,每个字符串常量(例如“Hello World”)都存储在内存中的某个位置

可能是:

0x10203040 : 0x48 [H]
0x10203041 : 0x65 [e]
0x10203042 : 0x6C [l]
0x10203043 : 0x6C [l]
0x10203044 : 0x6F [o]
0x10203045 : 0x20 [' ']
0x10203046 : 0x57 [W]
0x10203047 : 0x6F [o]
0x10203048 : 0x72 [r]
0x10203049 : 0x6C [l]
0x1020304A : 0x64 [d]
0x1020304B : 0x00 [\0]

因此,当使用内存中的上述值调用此函数时,[左侧是地址后跟':',右侧是字符的ascii值]

int strlen(const char *s)
{
    int n;

    for (n = 0; *s != ′\0′; s++)
        n++;
    return n;
}

strlen("Hello World");

那时,传递给的是字符数组第一个元素的地址的strlen值。0x10203040

请注意,地址是按值传递的。因此,strlen它拥有自己的“Hello World”地址副本。从 开始,直到我在内存中n = 0找到,我递增以及地址(然后递增到)等等,直到它找到地址并返回字符串长度。\0ns0x10203041\00x1020304B

于 2013-01-21T19:38:37.127 回答
3

"hello, world"

char是(type is char[13])的数组。表达式中的数组的值char是指向 的指针char。指针指向数组的第一个元素(即 is 的值"hello, world"&"hello, world"[0]

于 2013-01-21T19:24:40.107 回答
1

注意:

  • 指针(基本上)是指向内存地址的值。
  • 像这样的静态字符串"hello, word"存储在内存中的某处

因此,指针可以像指向存储在内存中的任何其他(动态)结构(如字符数组)一样简单地指向静态字符串。与其他提供的示例确实没有区别。

于 2013-01-21T19:25:59.960 回答
1

该函数是否将此字符串文字分配为其局部变量 *s 的值,然后使用 s 作为数组名称/指针?

是的

于 2013-01-21T19:27:37.477 回答
1

正如它在同一页的第一段(第 99 页,K&R2)中所说:

“根据定义,数组类型的变量或表达式的值是数组元素零的地址。”

“hello, world”的值将是“h”的地址。

于 2019-09-03T23:25:31.683 回答
0
char str[] = "Hello, world";
strlen(str);

C 中的字符串是字符数组,以 NULL 结尾('\0'),这意味着它应该在内存中的某个位置。

那么如上所述发送存储的字符串和如下直接发送有什么区别

strlen("Hello, World");

答案都是一样的,但是字符串的存储位置和处理方式,这里是编译器和堆栈。

编译器在编译时将字符串压入堆栈并发送堆栈中的起始地址(char*),调用函数看到指针并访问字符串。

编译器还在函数存在后添加代码以将堆栈恢复到正确的位置,从而删除创建的临时字符串 在此处输入图像描述 注意:以上是依赖于编译器的实现,但大多数编译器都是这样工作的

于 2020-10-21T08:41:29.977 回答