C 使用%s格式进行字符串操作
请解释以下输出:C 使用%s格式进行字符串操作,c,C,请解释以下输出: main() { char f[] = "qwertyuiopasd"; printf("%s\n", f + f[6] - f[8]); printf("%s", f + f[4] - f[8]); } 输出: uiopasd yuiopasd 例如,关于第一个printf: f[8]应表示字符'o' f[6]应表示字符'u' %s格式打印字符串(printf(“%s”,f)给出了整个“qwer
main()
{
char f[] = "qwertyuiopasd";
printf("%s\n", f + f[6] - f[8]);
printf("%s", f + f[4] - f[8]);
}
输出:
uiopasd
yuiopasd
例如,关于第一个printf
:
f[8]
应表示字符'o'
f[6]
应表示字符'u'
%s
格式打印字符串(printf(“%s”,f)
给出了整个“qwertyuiopasd”
)
那么它是如何组合在一起的,这里的字节操作是什么?假设字符遵循ASCII方案,以下字符的ASCII值是:
o (f[8]): 111
u (f[6]): 117
t (f[4]): 116
f
是指向char[]的指针,是指向f+6
的第一个语句值,该指针将指向数组的第六个元素,打印时,它将从第六个元素开始打印,直到遇到\0
为止
类似地,第二条语句的计算结果为f+5
,因此您可以将yuiopasd
作为输出
f+n是什么意思?
您可以在指针++,-,+,-上执行以下算术。指针存储内存地址,指针上的增量运算符将按类型大小增加地址值
例如,对于整数,如果
f
指向地址位置1000,并且我们在数组中存储4个字节int,那么f+1
将指向1004,这是数组中的下一个元素。这是一个简单的指针算法,在本例中更容易理解
int main(void)
{
char f[] = "9876543210";
printf("%s , f[6]=%d, f[8]=%d, f[6]-f[8]=%d, f + f[6] - f[8] = %s\n",f, f[6], f[8], f[6]-f[8], f + f[6] - f[8]);
结果是:
9876543210 , f[6]=51, f[8]=49, f[6]-f[8]=2, f + f[6] - f[8] = 76543210
f[n]
是数组的n
th索引元素的整数值
在此示例中,第6个和第8个元素的ASCII代码之间的差异为2
当我们向char指针添加
2
时,它将引用前面的元素2
chars,在我们的例子中,它是'7'
这是关于指针算术的。表达式f+f[6]-f[8]
的计算结果为char*
指针(与其第一个操作数类似,因为数组变量的名称在语法上等同于指向其第一个元素的指针),并将扩展为:
f+(int)'u'-(int)'o'
(其中“u”和“o”分别表示f[6]
和f[8]
)
表示字符'u'
和'o'
的值(在几乎所有使用ASCII系统的现代系统上)由6
分隔,因此表达式将6
添加到f
地址,并打印从其第7个元素开始的字符串
类似地,对于表达式
f+f[4]-f[8]
,这里的差异仅为5('t'-'o'
)。发布的代码中存在多个问题:
缺少的返回类型是过时的语法。您应该使用main
intmain()
- 编译调用时,
的原型不在范围内。这具有未定义的行为。您应该包括printf
- 表达式
具有未定义的行为:加法是左关联的,因此f+f[6]-f[8]
计算为f+f[6]-f[8]
(f+f[6])-f[8]
,即字母f[6]
的值不可能小于14(在ASCII中,其值为u
),因此117
远远超出字符串的末尾,因此是无效指针,并且计算f+f[6]
具有未定义的行为,尽管f+f[6]-f[8]
具有ASCII字符集的值'u'-'o'
。表达式应更改为6
f+(f[6]-f[8])
o
、u
和t
具有值111
、117
和116
。
f+(f[6]-f[8])
是f+('u'-'o')
它是f+(117-111)
或f+6
f+6
是f[6]
的地址,因此指向字符串“qwertyuiopasd”
的第7个字符的指针。打印此字符串会产生uiopasd
尝试写入printf(“%d\n”,f);printf(“%d\n”,f+f[6]-f[8]);它应该更容易理解(一个字符是一个字节)。提示:f[6]-f[8]='u'-'o'=6
,因为字符代码是连续的,u
是o
之后的第六个字符。因此f+f[6]-f[8]=f+6
@dxiv IIRC,C标准没有规定字母代码应该是连续的(与数字不同)。但它们几乎总是如此。@Adrian对,这里有一个指向指定位置的链接供参考。然而,考虑到引用的输出,OP的实现可能像大多数实现一样使用ASCII(或者UTF-8),“每个字符都有一个ASCII值”:它不一定要有。而且,考虑到问题中的代码,表达式f+f[6]-f[8]
是未定义的行为。我只是想回答用户得到的输出。谢谢反馈。你能解释一下你所说的“每个字符都有一个ASCII值”是什么意思吗:它不一定要有?字符的编码不能保证是C标准的ASCII码。C不依赖任何特定的字符编码。谢谢@M.NejatAydin我得到了问题,我也更新了我的答案。问题是表达式f+f[6]-f[8]
是未定义的行为,除非f[6]
的值小于或等于数组f
@M.nejaydin Yes的元素数,事实上,这是一个很好的发现。然而,在我的辩护中,我只是简单地解释了OP为什么会得到他们所做的输出:尽管标准没有定义行为,但所使用的指针算法在他们的情况下确实有效。