Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/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 使用%s格式进行字符串操作_C - Fatal编程技术网

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]
    ,即字母
    u
    的值不可能小于14(在ASCII中,其值为
    117
    ),因此
    f+f[6]
    远远超出字符串的末尾,因此是无效指针,并且计算
    f+f[6]-f[8]
    具有未定义的行为,尽管
    'u'-'o'
    具有ASCII字符集的值
    6
    。表达式应更改为
    f+(f[6]-f[8])
假设ASCII,字母
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为什么会得到他们所做的输出:尽管标准没有定义行为,但所使用的指针算法在他们的情况下确实有效。