int strlen(char *s)
{
char *p = s;
while (*p != '\0')
p++;
return (p - s);
}
p-s
给出高级字符数,即字符串长度
当我打印("%d")p或s时,我得到大数字(每次重新编译程序时都不同)
这些数字是否与指针的地址相关?单独使用p或s的printf%d是随机高数,但p-s
不是
答案 0 :(得分:4)
当您打印p
和s
等指针时,请使用%p
格式说明符。为了技术正确性,还要将它们转换为void *
:
printf("p is %p.\n", (void *) p);
printf("s is %p.\n", (void *) s);
如果使用不匹配的格式说明符进行打印,则行为未定义。
当您打印这些指针的值时,通常会看到传递给函数的字符串的地址开始(s
)并结束(p
)。 (C实现需要打印代表指针的东西。不需要将地址作为简单的数字,但是常见的C实现以十六进制打印地址。)这些可能是很大的值,因为操作系统,包括程序加载程序,在内存地址空间中指定各种位置供程序使用。
这些地址可能会有所不同,因为加载程序故意使用随机地址来阻止任何试图利用已知地址来破坏程序的攻击者。 (地址可能也有其他原因。)
p-s
是常量,因为您每次都传递相同的字符串,因此它开始的位置和结束位置之间的距离始终相同。
答案 1 :(得分:2)
tuple
是他们之间的区别。两个数字之间的差异基本上是偏移量。
来自p-s
二元运算符的结果是由此产生的差异 从第一个减去第二个操作数。
当你§6.5.6
时,你得到了什么。
但p-s
和p
包含应使用s
格式说明符打印的地址。
来自标准%p
(无法§6.5.6.8
的原因)
。如果指针操作数和结果都指向了元素 相同的数组对象,或者超过数组对象的最后一个元素, 评估不得产生溢出;否则,行为 未定义
另外你说每次&p-&s
和p
包含的值都是不同的,因为分配给程序的内存可能会不时变化。这就是地址变化的原因。
但差异总是相同的,因为它们与字符串的s
不同。
这是因为较低的地址通常为系统级程序保留。用户空间程序没有从那里分配chun。这就是为什么那些相当大的原因。
同样来自6.5.6
当减去两个指针时,两个指针都应该指向 相同的数组对象,或者超过数组对象的最后一个元素; 结果是两个数组的下标的差异 元素。结果的大小是实现定义的,它的 type(有符号整数类型)是ptrdiff_t中定义的 报头中。
要使用length
,ptrdiff_t
格式说明符将为printf
。
答案 2 :(得分:2)
让我们看一下关于指针减法的一些细节。引用C11
,章节§6.5.6
当减去两个指针时,两个指针都指向同一个数组对象的元素, 或者超过数组对象的最后一个元素;结果是差异 两个数组元素的下标。结果的大小是实现定义的, 并且其类型(有符号整数类型)在
ptrdiff_t
标头中定义为<stddef.h>
。 [....]
所以,底线
%td
打印p - s
的结果,输入ptrdiff_t
。p
和s
,您使用%p
转换说明符,因为它们都是指针类型。上述任何变化,您将导致undefined behavior