当我遇到这个C language implementation of Porters Stemming algorithm时,我发现了一个C-ism,我很困惑。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void test( char *s )
{
int len = s[0];
printf("len= %i\n", len );
printf("s[len] = %c\n", s[len] );
}
int main()
{
test("\07" "abcdefg");
return 0;
}
并输出:
len = 7
s[len] = g
然而,当我输入
test("\08" "abcdefgh");
或任何超过7的字符串常量,第一对括号中的对应长度(即test("\09" "abcdefghi");
输出
len = 0
s[len] =
但是像test("\01" "abcdefgh");
这样的输入会打印出该位置的字符(如果我们将第一个字符位置调用为1而不是0)
如果test( char *s )
读取第一对括号中的数字,则会出现(如何做到这一点我不确定,因为我认为s [0]只能读取一个字符,即'\' ')并在第二对括号中打印该索引处的最后一个字符+ 1的字符串常量。
我的问题是:好像我们将两个字符串常量传递给test( char *s )
。这里到底发生了什么,意思是,编译器如何在两对括号中“拆分”字符串?可能有的另一个问题是,"blah" "abcdefg"
形式的一串连续内存块?可能是我忽略了一些基本的东西,但即便如此我也想知道我忽略了什么。我知道这是一个基本概念,但我无法在网上找到一个明确的例子或情况来解释这一点,并且说实话,我不遵循输出。欢迎任何有用的评论。
答案 0 :(得分:8)
这里至少有三件事:
编译器连接彼此并列的文字字符串。 "a" "b"
与"ab"
完全相同。
反斜杠是一个转义字符,这意味着它不会被字面复制到结果字符串中。符号\01
表示“ASCII值为1的字符”。
符号\0...
表示八进制字符常量。八进制数字是基数8,由0到7(包括0到7)的数字组成。 8不是有效的八进制常量,因此"\08"
不遵循"\07"
。
答案 1 :(得分:4)
问题不在于字符串的长度,而是在\o
语法中用于指定字符串文字中的不可打印值。 \o
,\oo
和\ooo
表示 octal 常量,即一个字符,其值以base 8编写。自08
\08
以来\0
1}}不代表有效的基数为8的数字,它被解释为8
,后跟ASCII字符\10
。
要解决此问题,请将{8}表示为\010
或test("\007" "abcdefg");
test("\010" "abcdefgh");
:
\x
...或切换到十六进制,其中test("\x07" "abcdefg");
test("\x08" "abcdefgh");
test("\x09" "abcdefghi");
test("\x0a" "abcdefghij");
...
前缀使得基础对于随意读者更明确:
{{1}}
答案 2 :(得分:1)
\number
表示代码为值number
的字符。 number
以八进制解释,因此第一个非八进制数字终止该数字。因此"\07"
是包含代码7
的字符的单字符字符串,但\08
是一个双字符字符串,其中包含代码0
后跟数字{的字符{ {1}}。
此外,代码8
在C中用于表示字符串结尾的空终止符。所以第二个字符串在开头结束,因为它的第一个字节是终结符。这就是为什么第二个示例中字符串的长度为0
。
答案 3 :(得分:1)
当两个或多个字符串文字相邻(仅由空格分隔)时,编译器会将它们连接成一个字符串。因此"\07" "abcdefg"
相当于"\07abcdefg".
“\ 07”是八进制转义符。八进制转义在三位数或第一个非八进制字符后结束。因此,当您输入“\ _8”时,8
是非八进制字符,因此转义结束,0
存储在s[0]
。
现在,len
为0
,打印s[len]
将尝试打印s[0]
处的字符,该字符具有不可打印的ASCII代码(仅限高于{{1}的ASCII值以上的字符是可打印的。)