我正在阅读关于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; */
所有的工作。“
除了第一个调用示例之外,我觉得我理解所有这些:为什么或如何将字符串文字"hello, world"
视为char *s
?这怎么指针?函数是否将此字符串文字指定为其局部变量*s
的值,然后使用s
作为数组名称/指针?
答案 0 :(得分:12)
要理解像“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
开始,跟随uptil我在内存中找到\0
,我增加n
以及s
中的地址(然后增加到0x10203041
)依此类推,直到它在地址\0
找到0x1020304B
并返回字符串长度。
答案 1 :(得分:3)
"hello, world"
是char
的数组(类型为char[13]
)。表达式中char
数组的值是指向char
的指针。指针指向数组的第一个元素(即"hello, world"
的值为&"hello, world"[0]
)。
答案 2 :(得分:1)
请注意:
"hello, word"
这样的静态字符串存储在内存中的某个地方因此,指针可以很容易地简单地指向静态字符串,以及存储在内存中的任何其他(动态)结构(如字符数组)。与其他提供的示例实际上没有区别。
答案 3 :(得分:1)
函数是否将此字符串文字指定为其局部变量* s的值 然后使用s作为数组名称/指针?
是
答案 4 :(得分:1)
如同一页第一段(第99页,K&R2)所述:
“根据定义,变量的值或类型为array的表达式为 数组元素零的地址。”
“ hello,world”的值应为“ h”的地址。
答案 5 :(得分:0)
selectInput
C中的字符串是带有结尾NULL('\ 0')的字符数组,这意味着它应该在内存中的某些位置。
那么,按上述方式发送存储的字符串并按如下方式直接发送的字符串有什么区别
char str[] = "Hello, world";
strlen(str);
答案是相同的,但是字符串的存储位置和处理方式,是编译器和堆栈的所在。
编译器在编译时将字符串压入堆栈并在堆栈中发送起始地址(char *),调用函数会看到一个指针并访问该字符串。
编译器还会在函数存在后添加代码,以将堆栈恢复到正确的位置,从而删除创建的临时字符串 注意:以上内容取决于编译器的实现,但是大多数编译器都是以此方式工作的