【问题标题】:Issue when I copy a char array to another, using a template当我使用模板将 char 数组复制到另一个数组时出现问题
【发布时间】:2012-01-18 04:00:22
【问题描述】:

这是我的代码:

#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
using namespace std;

template <class T1, class T2>
void copy2(const T1 source[], T2 destination[] , int size){
    for (int i=0 ; i < size ; ++i){
        destination[i]=static_cast<T1>(source[i]);
    }
}



int main() {

    const char one[] = "hello";
    char two[5];

    cout << "one: " << one << endl;
    cout << "two: " << two << endl;

    copy2(one, two, 6);

    cout << "one: " << one << endl;
    cout << "two: " << two << endl;


    return 0;
}

但它输出:

一:你好

二:

一个:

二:你好

此外,数组“one”是常量,因此不应更改。

PS:当我以以下方式启动数组“二”时,它可以工作(但为什么??):

 char two[8];

但是,当我以以下两种方式启动它时,我会收到奇怪的错误:

 char two[6];

 char two[7];

【问题讨论】:

  • 您同时拥有copy2copyStuff。是哪个?
  • 对不起,我拼错了。但这不是问题。
  • 数组oneconst,是的,但这并不意味着它不能被修改。这意味着尝试这样做是未定义的行为

标签: c++ arrays templates copy char


【解决方案1】:

我的最佳猜测是 twoone 在堆栈中彼此相邻,如下所示:

  t   w   o   -   -   o   n   e   -   -    -
 --------------------------------------------
|   |   |   |   |   | h | e | l | l | o | \0 |
 --------------------------------------------

由于当two 的大小为 5 时,通过将大小 6 传递给 copy2 导致 two 的缓冲区溢出,所以内存最终会像这样:

  t   w   o   -   -   o    n   e   -   -   -
 --------------------------------------------
| h | e | l | l | o | \0 | e | l | l | o | \0 |
 --------------------------------------------

这就是为什么two 似乎持有“hello”而one 什么也没有显示(因为两个超出了它的缓冲区,现在空终止符是one 中的第一个字符)。

【讨论】:

  • 很可能会发生这种情况,但很可能根本不会发生这种情况。这里唯一确定的事实是它是一种未定义的行为.
【解决方案2】:

为了能够将源缓冲区复制到目标,您需要目标缓冲区足够大以容纳源缓冲区。

char two[5];

没有足够的空间来存储H,E,L,L,O,\0 ---> 大小为6
因此,您的目标数组two 的大小至少应为6,否则您的程序会超出数组的范围并导致未定义的行为。

另外,你应该初始化你的源缓冲区并且 NULL 终止它。否则它包含垃圾字符。

char two[6]={0};

通过上述修改,您的 program works 符合我的要求。

【讨论】:

  • 我假设您在 Q 中给出的代码中调用 copystuff() 而不是 copy2() 是一个错字。
  • 非常感谢!但是我仍然必须澄清为什么当我没有将源缓冲区初始化为 NULL 时它会擦除“one”数组的值。因为即使我将目标缓冲区大小设置为 6,而无需将源缓冲区初始化为 NULL,我也会得到:一:你好二:一:你好二:你好
  • @user1155340: 如果目标缓冲区的大小 (5) 小于源 (6) 则将 6 字节写入目标缓冲区会导致写入超出目标边界的数据缓冲区。可能,源缓冲区被放置在目标缓冲区之后的堆栈上,并且包含 \0 的额外 1 字节被写入源缓冲区位置。这使您的源缓冲区为 NULL。这可能会发生,但无论如何覆盖数组的边界会导致 Undefined Behavior 并且您的程序可能会显示任何此类奇怪的行为,这些行为可能会或可能不会被解释。
  • @Als 基本上我在回答中所说的一切 :)
  • @Marlon:不是真的。您错过了说这是未定义的行为,实际上可以看到任何行为,虽然我们只能猜测可能会发生什么从理论上讲,UB 可能会导致任何不需要解释的事情。行为本质上是 UB不保证任何解释。是的,我对 Q 显示 UB 的回答通常不会对此提供任何解释,因为永远不能依赖此类行为来作为您的程序的基础。只有一条规则避免使用 UB 编写任何代码,如果您不这样做难道你注定没有任何解释。
猜你喜欢
  • 2023-03-09
  • 2020-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-13
  • 1970-01-01
  • 2022-07-05
相关资源
最近更新 更多