Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C、 不使用malloc初始化结构_C_Oop_Constructor_Struct - Fatal编程技术网

C、 不使用malloc初始化结构

C、 不使用malloc初始化结构,c,oop,constructor,struct,C,Oop,Constructor,Struct,我将避免使用malloc来初始化结构,我正在寻找使用oo风格(如果可能)设计C软件的最佳实践 只有C99,而不是C++ 第一个问题,当像对象一样使用结构时,什么更可取?是否键入其指针 以下是我的测试(所有工作都使用gcc编译器): 案例1 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct sItem{ int n; char* text; } o

我将避免使用malloc来初始化结构,我正在寻找使用oo风格(如果可能)设计C软件的最佳实践

只有C99,而不是C++

第一个问题,当像对象一样使用结构时,什么更可取?是否键入其指针

以下是我的测试(所有工作都使用gcc编译器):

案例1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct sItem{
    int n;
    char* text;
} oItem, *Item;

int main(int argc, char** argv) {
    Item i1=(&(oItem){.n=1, .text="A"});
    Item i2=(&(oItem){.n=100, .text="ABC"});
    printf("%d, %s, %d\n", i1->n, i1->text, sizeof(*i1)); // 1, "A", 8
    printf("%d, %s, %d\n", i2->n, i2->text, sizeof(*i2)); // 1, "ABC", 8
    return (EXIT_SUCCESS);
}
#包括
#包括
#包括
类型定义结构站点{
int n;
字符*文本;
}oItem,*项目;
int main(int argc,字符**argv){
项目i1=(&(oItem){.n=1.text=“A”});
项目i2=(&(oItem){.n=100,.text=“ABC”});
printf(“%d,%s,%d\n”,i1->n,i1->text,sizeof(*i1));//1,“A”,8
printf(“%d,%s,%d\n”,i2->n,i2->text,sizeof(*i2));//1,“ABC”,8
返回(退出成功);
}
这是可行的,但我认为不应该,因为文本没有初始化为包含字符串。 这是一段无效的代码吗

案例2

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct sItem{
    int n;
    char text[5];
} oItem, *Item;

int main(int argc, char** argv) {
    Item i1=(&(oItem){.n=1, .text="A"});
    Item i2=(&(oItem){.n=100, .text="ABC"});
    printf("%d, %s, %d\n", i1->n, i1->text, sizeof(*i1)); // 1, "A", 12
    printf("%d, %s, %d\n", i2->n, i2->text, sizeof(*i2)); // 1, "ABC", 12
    return (EXIT_SUCCESS);
}
#包括
#包括
#包括
类型定义结构站点{
int n;
字符文本[5];
}oItem,*项目;
int main(int argc,字符**argv){
项目i1=(&(oItem){.n=1.text=“A”});
项目i2=(&(oItem){.n=100,.text=“ABC”});
printf(“%d,%s,%d\n”,i1->n,i1->text,sizeof(*i1));//1,“A”,12
printf(“%d,%s,%d\n”,i2->n,i2->text,sizeof(*i2));//1,“ABC”,12
返回(退出成功);
}
这是可行的,我认为这是正确的,是吗

案例3

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define Item_new(i, n, s) (&(oItem){0});Item_ctor(i, n, s);
#define Item_neww(i, x, s) (&(oItem){\
        .n=x,\
        .text=s\
})

typedef struct sItem{
    int n;
    char text[5];
} oItem, *Item;


void Item_ctor(Item i, int n, char* text){
    i->n=n;
    strcpy(i->text, text);
}

int main(int argc, char** argv) {
    Item i1=Item_new(i1, 10, "ABC");
    Item i2=Item_neww(i2, 10, "ABC");
    printf("%d, %s, %d\n", i1->n, i1->text, sizeof(*i1)); // 10, "ABC", 12
    printf("%d, %s, %d\n", i2->n, i2->text, sizeof(*i2)); // 10, "ABC", 12
    return (EXIT_SUCCESS);
}
#包括
#包括
#包括
#定义新的(i,n,s)(&(oItem){0});项目(i,n,s);;
#定义新项目(i、x、s)(&(oItem){\
.n=x\
.text=s\
})
类型定义结构站点{
int n;
字符文本[5];
}oItem,*项目;
无效项目(项目i、整数n、字符*文本){
i->n=n;
strcpy(i->text,text);
}
int main(int argc,字符**argv){
第i1项=新项目(第i1、10、ABC);
i2项=新项目(i2,10,“ABC”);
printf(“%d,%s,%d\n”,i1->n,i1->text,sizeof(*i1));//10,“ABC”,12
printf(“%d,%s,%d\n”,i2->n,i2->text,sizeof(*i2));//10,“ABC”,12
返回(退出成功);
}
我认为这很好,但是隐藏了代码,可能是有害的,你认为呢?
在案例3中,最好的选择是什么:宏还是构造函数?

案例3是我经常看到并推荐的。将代码包装在构造函数中是非常好的-为什么隐藏代码会成为一个问题?事实上,这是一个特性——从实现中隐藏接口。此外,不要为此使用宏——这对于宏来说太复杂了,尽管如此,宏通常是邪恶的


在我看来,方法1和2非常难看(事实证明,它们也是UB)并且不可读。此外,案例1不是常量正确的,或者使用案例2(因为它调用了未定义的行为,所以不要使用它),或者将“text”声明为
const char*

不做3,即包含未受保护的
的宏让我非常紧张

相反,我将用以下内容替换您的“new”和“ctor”

#define Item_new(i, n, s) Item_ctor(&(oItem){0}, n, s)

Item Item_ctor(Item i, int n, char* text){
    if (i) {
      i->n=n;
      strncpy(i->text, text, 4);
    }
    return i;
}
这并没有打破用户对
Item\u new
的期望:一个真正的 类似于返回值的宏的函数


ctor应该进行必要的检查,并且永远不要覆盖内存,
i->text[4]
将始终是
0
。(最好使用符号常量而不是
5
,并将其用于
strncpy
调用。)

示例1和2不是有效代码。您不能接受临时文件的地址并期望它包含有效值。如果需要堆栈分配的指针,请使用alloca。2是有效的,为什么说它不是有效的?因为您使用的是临时值的地址,这是未定义的行为。在案例2中,我不使用临时值的地址…我不会使用不反映它是指针的名称来定义指针。如果Item_ptr太长,我只会使用Item*。谢谢,在案例3中,使用宏是一种更有效的初始化结构的方法,因为我使用literal struct复合初始化,使用ctor我必须首先将所有结构数据初始化为0(使用{0}),然后设置它们,这是真的吗?感谢again@blow它不是效率最低,就是缺陷很小,不值得编写和维护这样一个宏。在一个性能差、内存非常少的嵌入式设备中,您会选择哪一种?好的,谢谢,我会按照您建议的方向来做,但我对我要做的事情有些怀疑,我认为我选择OO这样的设计模式是错误的,但为此,我可能会打开一个新的线程。再次感谢。@H2C03在示例3中,main中的两个指针指向的数据驻留在哪里?