2011-05-23 34 views
2

下面是一个程序的功能:字符串连接到另一个没有分配,这是为什么?

//read the specified file and check for the input ssn 
int readfile(FILE *fptr, PERSON **rptr){ 
    int v=0, i, j; 
    char n2[MAXS+1], b[1]=" "; 

    for(i=0; i<MAXR; i++){ 
     j=i; 
     if(fscanf(fptr, "%c\n%d\n%19s %19s\n%d\n%19s\n%d\n%19s\n%19s\n%d\n%d\n%19s\n\n", 
        &rptr[j]->gender, &rptr[j]->ssn, rptr[j]->name, n2, &rptr[j]->age, 
        rptr[j]->job, &rptr[j]->income, rptr[j]->major, rptr[j]->minor, 
        &rptr[j]->height, &rptr[j]->weight, rptr[j]->religion)==EOF) { 
      i=MAXR; 
     } 
     strcat(rptr[j]->name, b); 
     //strcat(rptr[j]->name, n2); 
     if(&rptr[MAXR]->ssn==&rptr[j]->ssn) 
      v=j; 
    } 
    return v; 
} 

的注释行就是这样,因为某些原因,阵列“B”包含字符串“N2”尽管一个明显缺乏分配。这发生在第一次strcat调用之前,但在fscanf调用之后。

它确实达到了预期的目标,但是为什么n2连接到b的末尾,特别是当b仅为1个数组元素保留空间时?

下面是变量定义的的fscanf呼叫后一个片段:

*rptr[j]->name = "Rob" 

b = " Low" 

n2= "Low" 
+0

b不是空终止......它只有一个字符的空间......空间......它可能有东西在里面,因为你溢出了一个缓冲区。 – forsvarir 2011-05-23 14:13:04

回答

3

它有效,因为你很幸运。 bn2碰巧在内存中以正确的顺序彼此相邻。 C不会对数组进行边界检查,并且会很高兴地让你溢出。所以,你可以声明一个这样的数组:

char someArray[1] = "lots and lots of characters"; 

C编译器(当然旧的)会认为这是好的,即使显然不是在someArray足够的空间来存储多个字符。我不确定它是否定义了在这种情况下它会做什么(我怀疑不是),但是在我的编译器中它将总体限制为数组的大小,所以它不会溢出边界(someArray=={'l'})。

你的情况是一样的(尽管不太极端)。 char b[1]正在创建一个有足够空间存储1个字节的数组。你在这个字节中放了一个空格,所以没有空终止符。它会一直拷贝内存直到它到达一个空终止符,因此它会一直继续下去,直到它找到一个,即使它不是直到下一个字符串的末尾(这就是你的情况发生了什么)。

如果您已经使用C++编译器,它会抛出至少一个警告(或更可能是错误的),告诉你,你想放太多的物品入阵。

+0

+1,虽然我不会称之为获取“幸运”,因为它不会彻底炸毁,并让你知道有一个明显的问题。该行为未定义为每6.7.8/2:“没有初始化程序将尝试为未包含在被初始化的实体中的对象提供值” – 2011-05-23 15:05:10

+0

@John Bode:是的,我是幸运50:50自己...谢谢供参考:) – forsvarir 2011-05-23 15:08:09

2

B需要是大小为2,1的空间中,1空。

+0

换句话说,'b [1] =“”;'等同于'b [1] = {'','\ 0'};' – Lundin 2011-05-23 14:21:40

+0

@Lundin:No,'b [1] =“”; '相当于'b [1] = {''};'。 'b [2] =“”;'相当于'b [2] = {'',0};'... – forsvarir 2011-05-23 14:24:27

+0

@forsvarir公平的,我只是想说明它为什么是一个错误。 – Lundin 2011-05-23 14:28:29

相关问题