2014-01-24 134 views
4

我正在研究从bsd的libc函数strtok的代码,当我在我的机器上运行它时, 程序收到信号SIGSEGVs[-1] = 0。 代码如下是links [-1] = 0是什么意思?

s[-1] = 0对不对?

这是我的代码:

#include <stdio.h> 
#include <stdlib.h> 
#include "strtok.c" 

int main(int argc, char* argv[]) { 
    char* str = "xxxx xxxyy fdffd"; 
    const char* s = " "; 

    char* token = strtok(str, s); 

    while (token != NULL) { 
     printf("%s\n", token); 
     token = strtok(NULL, s); 
    } 

    return 0; 
} 
+2

是的,没错。但是,您的调用代码可能不是。 –

+2

可能'[-1] = 0'是正确的。可能调用它的代码是错误的。 –

+1

http://www.codinghorror.com/blog/2008/03/the-first-rule-of-programming-its-always-your-fault.html –

回答

6
s[-1] 

被扩展为:

*(s - 1) 

因此,如果结果指向有效的存储器,所述代码被定义。

+2

(-1)[s]将同样有效。疯狂! –

+0

它有助于记住C不*真*有数组,只是指针。 –

+2

@HotLicks C肯定有数组。 http://eli.thegreenplace.net/2009/10/21/are-pointers-and-arrays-equivalent-in-c/对数组做[[]]是未定义的b。 – this

1

它应该是OK事业几行上面确实小号++,所以最坏的情况下,我们正在与(S + 1)-1。

3

这是可以的,因为s是我们可以从C99标准草案看指针E1[E2] is identical to (*((E1)+(E2)))从部分6.5.2.1数组下标说(重点煤矿):

后缀表达式后跟表达式在方括号[]中是下标 指定数组对象的元素。下标运算符[] 的定义是E1 [E2]与(*((E1)+(E2)))相同。由于 适用于二元运算符的转换规则,如果E1是一个数组对象(等价地,指向数组对象的初始元素的指针)并且E2是一个整数,则E1 [E2]指定第E2个E1的元素(从零开始计数)。

如果s是一个数组,但这不会是有效的代码,因为我们将访问不属于该数组的内存,这将是未定义的行为。

1

无论s[-1] = 0是“正确”或“错误”将取决于s运行时间值。

s[-1] = 0本身没有什么内在错误或不寻常的。

3

s[-1]指的是之前的对象s指向的对象。根据C的规则,s[-1]相当于*(s-1)。这个:

  • 计算s-1。结果是指向s指向的对象之前的对象的指针,s+1是指向s之后的对象的指针的相同方式。
  • 推断它,它产生指向对象的左值。

因此,s[-1] = 0将0指定给s指向的对象之前的对象。

s[-1]是合法代码,如果s指向第一个元素之后的数组元素(因此确保它之前有一个元素)或s指向数组的末尾。 (这也是合法的,如果s指向一个超出单个对象的数组,这是非常不寻常的用途。)

0

只是一个预感,但我相当肯定FreeBSD的strtok(3)是相当稳定的,相当不错的测试。

schar*; s[-1]s指向的那个字符设置为NUL

我们可以看到您的实际代码是strtok(3)吗?这个问题可能在你的设置中,可以这么说。此外,您是否阅读过手册页?

第一次调用strtok()时,应该指定str;后续调用,希望从同一个字符串中获得更多的标记, 应该传递一个空指针。必须每次提供分隔符字符串sep, ,并且可能会在两次调用之间进行更改。