【问题标题】:Passing structs holding static arrays in C++在 C++ 中传递保存静态数组的结构
【发布时间】:2014-05-02 11:18:20
【问题描述】:

我想知道是否可以在 C++ 中传递/返回保存静态分配数组的结构。例如:

typedef struct t{
    char name[32];
    int id;
}t;

t foo(char name[]){
    t my_t = {name, 0};
    return my_t;
}

int main(){
    t main_t = foo("a struct");
    printf("%s", main_t.name); //is this safe to access? 
    return 0;
}

当它按值返回结构时,我猜它不会复制数组名称,只复制指向它的指针。

编辑:只是为了澄清一些事情。我知道char *var 等于函数参数中的char var[]。我很快就编写了这段代码,甚至没有对其进行测试。我知道它绝对不是世界上最好的代码,我不会建议任何人在现实生活中使用它。 理想情况下,我会动态分配结构并传递指针,但是,我正在教一个人用 C/C++ 编程。这是一个不需要人知道动态分配或指针的国家考试,这就是为什么*根本没有真正使用。

问题实际上是关于是否可以返回一个包含静态分配数组的结构。

我们可以改用这段代码吗:

#include <iostream>

struct t{
    char name[32];
    int id;
};

t foo(int id){
    t my_t;
    my_t.id = id;
    for(char i = 0; i < 31; i++){
        my_t.name[i] = 'a';
    }
    my_t.name[31] = '\0';
    return my_t;
}

int main(){
    t main_t = foo(0);
    std::cout << main_t.name; //is this safe to access? 
    return 0;
}

【问题讨论】:

  • 这不应该编译,因为您试图在此处将 char* 分配给 char[] t my_t = {name, 0}
  • 在大多数情况下混合使用 C 和 C++ 并不是一个好主意。例如,C++ 答案可能会定义复制构造函数和复制赋值,而 C 答案可能会引入克隆方法。
  • foo(char name[]) 没用。基本上它是一个没有任何大小的foo(char*)
  • @MrSpreadsheet 哪种语言 c 或 c++?

标签: c++ arrays struct


【解决方案1】:

可以的。

但不应该这样做:替代方案是 std::stringstd::array。您可以免费获得副本、分配、解除分配等!

struct t {
    std::string name;
    int id;
    std::array<int, 10> integers;
};

...

t main_t = {"a struct"};
main_t.integers[5] = 5;
t copy = main_t;
assert( copy.name == "a struct" );
assert( copy.id == 0 );
assert( copy.integers[5] == 5 );

【讨论】:

    【解决方案2】:
    1. 您的代码中没有 static 数组。

    2. 当您按值返回 t 实例时,它复制数组的内容。

    3. 问题在于您如何初始化 t 实例,而不是您如何返回它。


    改变这个:

    t my_t = {name,0};
    

    到这里:

    t my_t = {0};
    strncpy(my_t.name,name,sizeof(my_t.name)-1);
    

    或者到这里,如果你想避免使用库函数:

    int i;
    t my_t;
    for (i=0; i<sizeof(my_t.name)-1 && name[i]!=0; i++)
        my_t.name[i] = name[i];
    my_t.name[i] = 0;
    my_t.id = 0;
    

    【讨论】:

    • 点击链接 ;) 如果源字符串比目标字符串长,它不会被空终止。 strncpy 不复制字符串,因为结果不一定是“字符串”(以空结尾)。
    • @leemes:这就是t my_t = {0} 的用途。
    • 现在你有sizeof(...)-1 似乎是安全的,但我记得你以前没有。
    • @leemes:是的,我在提交初始答案后立即添加了它。谢谢。
    【解决方案3】:

    你的程序有错误;您正在尝试复制指向数组的指针,而应将指针指向的内容复制到数组中。应该是这样的

    #include <algorithm>
    #include <cstring>
    
    struct t
    {
        char name[32];
        int id;
    };
    
    t foo(const char *name)
    {
        t my_t = {};
        const size_t len = std::strlen(name);
        const size_t max_len = sizeof(t::name) / sizeof(t::name[0]) - 1u;
        std::copy(name, name + std::min(len, max_len), my_t.name);
        return my_t;
    }
    
    int main()
    {
        t main_t = foo("a struct");
        printf("%s", main_t.name);
    }
    

    至于你的问题

    我想知道是否可以在 C++ 中传递/返回包含静态数组的结构

    是的,没关系,整个结构将被复制(或移动,取决于类型)到调用端的变量。

    【讨论】:

    • 而且,你会在编译时知道数组长度,所以你不能传递给小缓冲区。
    【解决方案4】:

    传递包含数组的结构是可以的。然而,这条线并没有像你想象的那样做:

    t my_t = {name, 0};
    

    使用指定的初始化语法,它相当于:

    t my_t = {  .name[0] = name;  .name[1] = 0; };
    

    t 的第一个成员是一个包含 32 个元素的数组,因此前 32 个初始化器应用于这 32 个chars。除非您使用更多大括号,但每个元素仍需要一个初始化程序,否则没有什么神奇的方法可以从大括号封闭的初始化程序中获取 strcpy

    关于使用指针初始化char,您应该会收到一个编译器错误。

    【讨论】:

    • 所以基本上,当我在编译时在结构中定义数组的大小时,内存是在结构本身内部分配的,而不是指针?然后当我返回它时,整个数组都会被复制?这是困扰我的问题。我的意思是,结构访问适用于偏移量,所以这是合乎逻辑的。
    猜你喜欢
    • 2017-09-20
    • 1970-01-01
    • 1970-01-01
    • 2011-02-08
    • 1970-01-01
    • 1970-01-01
    • 2021-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多