当我在我的机器上运行时,我正在研究bsd的libc函数strtok的代码,
该程序在SIGSEGV
中收到了信号s[-1] = 0
。
这是代码的link。
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;
}
答案 0 :(得分:6)
s[-1]
扩展为:
*( 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
是一个数组,那么这将不是有效的代码,因为我们将访问不属于数组的内存,这将是未定义的行为。
答案 2 :(得分:3)
s[-1]
指的是s
指向的对象前面。
根据C的规则,s[-1]
相当于*(s-1)
。这样:
s
指向的对象之前指向对象的指针,与s+1
之后指向对象的指针的方式相同。因此,s
在s[-1] = 0
指向的对象之前为对象指定0。
s
是合法代码,如果s[-1]
指向第一个元素后面的数组元素(从而确保在它之前有一个元素)或s
指向一个元素之外的元素数组的结尾。 (如果s
指出一个超出不在数组中的单个对象,这也是合法的,这是一种不寻常的用途。)
答案 3 :(得分:1)
应该没问题,因为它上面几行就是s ++,所以最糟糕的情况我们正在使用(s + 1)-1。
答案 4 :(得分:1)
s[-1] = 0
是“正确”还是“错误”取决于s
的运行时值。
s[-1] = 0
本身没有任何内在错误或不寻常的错误。
答案 5 :(得分:0)
只是预感,但我相当确定FreeBSD的strtok(3)
非常稳定且经过充分测试。
s
是char*
; s[-1]
将s
指向的字符设置为NUL
。
我们可以看到您调用strtok(3)
的实际代码吗?可以这么说,问题可能在你的设置中。此外,您是否阅读了手册页?
第一次调用
strtok()
时,应指定str
; 后续调用,希望从同一串中获取更多令牌, 应该传递一个空指针。分隔符字符串sep
, 必须每次都提供,并且可以在不同呼叫之间改变。