C字符串副本,数组大小

时间:2014-10-04 12:24:14

标签: c pointers strcpy

我试图通过编写自己的函数来模仿strcpy的工作方式。我的问题更具体到数组的大小。

我正在尝试将stringA的内容复制到stringB,我已将其声明为1。

  1. 我不应该收到错误消息,指出stringB太小而无法容纳stringA吗?原因是,我怀疑我没有收到错误是因为数组名称StringB被转换为指针?

  2. 为什么char str[1] = "abcd"非法?

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void strCopy(char *source,char *destination) {
        printf("%p,%p\n",source,destination);
        while (*source != '\0') {
            *destination = *source;
            printf("> %c,%p,%p\n",*source,source,destination);
            source++;
            destination++;
        }
    
        *destination = '\0';
    }
    
    int main(int argc,char *argv[]) {
       char stringA[] = "To be or not to be.";
       char stringB[1];
       strCopy(stringA,stringB);
       printf("StringB: %s\n",stringB);
    
       return (0);
    }
    

2 个答案:

答案 0 :(得分:2)

1)我不应该得到一个错误,说stringB太小而无法容纳stringA吗?

由于编译器内存分配方案,您没有收到任何错误。编译器很可能先将内存分配给stringB,然后再将stringA分配给stringA。因此,如果stringB具有内存位置1000(仅一个字节),则stringA将具有从1001到1020的内存位置(包括用于NULL的空间)。因此,当您尝试将内容从stringA复制到stringB到您的函数时,它实际上从位置1001复制到1000,然后从1002复制到1001,依此类推,所以根据您的程序,如果是这样的话,您必须输出如图所示。你似乎在打印字符串的地址。查看字符串的地址并检查是否是这种情况。再次,这仅仅是string2首先被分配内存而不是stringA的结果。在编译器的所有变体中,这都不是必要的,每次都是答案。

stringB:成为或不成为

stringA:o是或不是蜜蜂

现在你没有收到错误,因为两个数组都存在于堆栈帧中,并且两者都是通过指针访问的,所以编译器在使用指针完成数据复制时并不关心数组的大小。它只是复制,直到你在允许的内存空间。如果不是这种情况并且stringA首先出现在内存中,那么你会得到分段错误。

2)为什么char str [1] =&#34; abcd&#34;那么非法?

这不是一个非常不同的情况,你只分配一个字节到字符串,并用比其大小更多的字符初始化它。请注意,您的数据副本是在运行时完成的,但是这个初始化是在编译时,因此编译器知道数组的大小并会向您显示警告,这不是非法的,但编译器只将第一个字符分配给字符串,您可能会得到不可预测的结果是因为最后没有空格留给NULL字符。

答案 1 :(得分:1)

1)我不应该得到一个错误,说stringB太小而无法容纳stringA吗?

根据内存空间stringB的位置,您可能不会收到错误。如果stringB指针放在应用程序内存的中间,那么你当然可以写出超过其声明边界的值。你只需要覆盖用于存储其他值或功能的内存。 C / C ++永远不会像其他语言那样检查你是否超过了数组长度,例如: Java的。

2)为什么char str 1 =“abcd”非法呢?

由于程序的行为完全根据您的实现而未定义,因此很难准确描述正在发生的事情。

另请参阅以下帖子:why doesn't my program crash when I write past the end of an array?