请解释为什么这个C代码给我一个分段错误?
我是一个试图学习C语言的初学者。当我运行它时,下面的代码给了我一个分段错误。谁能解释一下原因,或者告诉我我的错误请解释为什么这个C代码给我一个分段错误?,c,pointers,struct,segmentation-fault,C,Pointers,Struct,Segmentation Fault,我是一个试图学习C语言的初学者。当我运行它时,下面的代码给了我一个分段错误。谁能解释一下原因,或者告诉我我的错误 struct frac sum(struct frac f1, struct frac f2); struct frac { int *numer; int *denom; }; struct frac sum(struct frac f1, struct frac f2) { struct frac rv; *rv.numer = (*f1.numer)*(*f2.denom) +
struct frac sum(struct frac f1, struct frac f2);
struct frac {
int *numer;
int *denom;
};
struct frac sum(struct frac f1, struct frac f2) {
struct frac rv;
*rv.numer = (*f1.numer)*(*f2.denom) + (*f2.numer)*(*f1.denom);
*rv.denom = (*f1.denom)*(*f2.denom);
return rv;
}
int main() {
int n = 5;
int d = 10;
struct frac myFrac1 = {&n, &d};
struct frac myFrac2 = {&n, &d};
struct frac myFrac3 = sum(myFrac1, myFrac2);
return 0;
}
试试这个
struct frac sum(struct frac f1, struct frac f2);
struct frac {
int *numer;
int *denom;
};
struct frac sum(struct frac f1, struct frac f2) {
struct frac rv;
rv.numer = (int*)malloc(sizeof(int));
rv.denom = (int*)malloc(sizeof(int));
*rv.numer = (*f1.numer)*(*f2.denom) + (*f2.numer)*(*f1.denom);
*rv.denom = (*f1.denom)*(*f2.denom);
return rv;
}
int main() {
int n = 5;
int d = 10;
struct frac myFrac1 = {&n, &d};
struct frac myFrac2 = {&n, &d};
struct frac myFrac3 = sum(myFrac1, myFrac2);
return 0;
}
结果是rv.numer
和rv.denom
在末尾都指向100。“…代码在运行时给了我一个分段错误。谁能解释原因,或者告诉我错误?”
首先,在调试模式下编译时会出现一些问题,如果您能够看到这些问题,并通过解决每一个问题来做出响应,则可能会防止出现seg故障:
当I编译时,出现正常警告:
不初始化变量是最常被忽略的错误之一,但是程序员(新的和旧的)会犯代价高昂的错误。总是初始化
为什么seg故障-在您的原始代码中,我在运行时看到这一点:
尝试取消引用未初始化的指针几乎总是会导致分段错误 下面是一些解决上述错误的建议:
为了在整个示例中保持可读性,代码的自适应使用
typedef
创建frac\u s
。以原始帖子的方式使用指针需要动态内存分配,而非指针(即struct
成员)也同样适用。因此,请注意使用非指针成员。下面的指针使用仅限于函数参数和返回类型sum(,)
,因此大大简化了代码,但需要动态内存分配和free()
。将以下内容与代码进行比较,以查看更改的范围
typedef struct {
int numer;
int denom;
}frac_s;
frac_s * sum(frac_s *f1, frac_s *f2);
frac_s * sum(frac_s *f1, frac_s *f2) {
frac_s * rv = calloc(1, sizeof(*rv)) ;
if(rv)
{
rv->numer = (f1->numer)*(f2->denom) + (f2->numer)*(f1->denom);
rv->denom = (f1->denom)*(f2->denom);
}
return rv;
}
int main(void) {
int n = 5;
int d = 10;
frac_s myFrac1 = {n, d};
frac_s myFrac2 = {n, d};
frac_s *myFrac3 = sum(&myFrac1, &myFrac2);
if(myFrac3)
{
//use myFracs;
free(myFracs);
}
return 0;
}
程序将在第二行崩溃
struct frac rv;
*rv.numer = (*f1.numer)*(*f2.denom) + (*f2.numer)*(*f1.denom);
因为,您在堆栈中定义了rv。房车号码可以是任何东西
在大多数情况下,*(rv.numer)是一个你不能写的地方。你为什么在这里使用指针
rv.numer
和rv.denom
未初始化为任何对象,因此取消引用它们是未定义的行为。好的,我从rv.numer和rv.denom中删除了*,但现在我收到警告:“int”中的“int*”赋值会使整数中的指针不带强制转换。如果我尝试将表达式的右侧强制转换为一个指针,如rv.denom=(int*)((*f1.denom)*(*f2.denom))代码>我收到警告:从不同大小的整数转换为指针。因为您使用的是指针。您需要将rv.numer
和rv.demon
指向某个对象(例如malloc
调用的结果或指向现有int的指针,就像您在main
中对其他两个对象所做的那样),或者使用numer
和denom
整数而不是指针。因此,我首先需要将内存分配给rv.numer
和rv.denom
,然后才能让它们指向指针上的某些算术结果?请不要编辑您的原始帖子,从而更改代表该问题本质的内容你的问题是关于什么的。编辑应限于格式化和/或添加新信息以澄清评论中的问题。更改代码会使新观众感到困惑,并导致通过评论和答案提供的内容被误解。出于这个原因,我已经将帖子回滚到原来的版本。这些添加的括号不会改变任何事情*rv.numer
和*(rv.numer)
是等价的。我不这么认为,*rv.numer
会先做*rv,然后尝试获取numer元素。但是,*(rv.numer)
将首先找到numer元素,然后在其上执行*。否。看<代码>
(结构和联合成员访问)的优先级高于*
(间接(取消引用))。该页面甚至给出了一个示例,说明*p++
如何等效于*(p++)
,后缀增量运算符与
具有相同的优先级。我不知道您试图对编辑做什么。这是一个C问题,而不是C++问题—您有指针作为结构成员。在存储任何内容之前,需要为它们分配内存。另一个选项是将它们指向已经分配的内存,就像在struct frac myFrac1={&n,&d}代码>