Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/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:在函数中复杂使用、结构并集和并集作为参数,产生未定义的行为_C_Function_Pointers_Struct_Unions - Fatal编程技术网

C:在函数中复杂使用、结构并集和并集作为参数,产生未定义的行为

C:在函数中复杂使用、结构并集和并集作为参数,产生未定义的行为,c,function,pointers,struct,unions,C,Function,Pointers,Struct,Unions,我目前正在尝试开发一个低规模的程序,以模拟使用工会作为参数的方法,然后使用相同的想法开发一个更大规模的程序。联合体由两个结构组成 在我的程序中,第一个结构有一个无符号int,第二个结构有81个元素的char数组。在下面的代码中,union对成员具有两种类型的结构。接下来是函数ufuncx的原型;它有两个参数:联合指针和int 我试图实现一种方法,在这种方法中,我可以将一个联合指针传递到一个函数中,该函数指向在联合外部定义的两个结构地址之一,这两个地址也是联合结构成员的一部分 源代码列表: /*

我目前正在尝试开发一个低规模的程序,以模拟使用工会作为参数的方法,然后使用相同的想法开发一个更大规模的程序。联合体由两个结构组成

在我的程序中,第一个结构有一个无符号int,第二个结构有81个元素的char数组。在下面的代码中,union对成员具有两种类型的结构。接下来是函数ufuncx的原型;它有两个参数:联合指针和int

我试图实现一种方法,在这种方法中,我可以将一个联合指针传递到一个函数中,该函数指向在联合外部定义的两个结构地址之一,这两个地址也是联合结构成员的一部分

源代码列表:

/*
   this is a program test to see if different types of union members can `enter code as
   function arguments of the same union type.
*/

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

struct id_num
{
   unsigned short int idnumber;
};

struct namedisc
{
   char name[81];
};

union combo_x
{
   struct id_num numtest;
   struct namedisc note;
};

int ufuncx(union combo_x *, int);

int main(void)
{

//step 1:

    union combo_x *a, *b;

    //struct data

    struct namedisc text;
    struct id_num age;

//step 2a:

    //pointer *a - uses the id_num struct

    age.idnumber = 25;
    a->numtest = age;

//step 2b:

    //pointer *b - uses the namedisc struct

    strcpy(text.name,"John Doe\0");
    b->note = text;

//step 3:

      /*=- if you comment this, a pointer error in run time occurs -=*/
      printf(".... %s\n",b->note.name);

//step 4:

    //show output

    ufuncx(a,1);
    ufuncx(b,2);

    return 0;
}

int ufuncx(union combo_x *data,int part)
{

    if(part < 1 || part > 2)
    {
        printf("we dont have that part...\n");
        return -1;
    }

    if(part == 1)
    {
        printf(" age = %d ",data->numtest.idnumber);
    }

    if(part == 2)
    {
        printf("name = %s ",data->note.name);
    }

    printf("(it works!)\n");

    return 0;
}
这看起来不错,而且似乎有效,但存在一个问题。 在第3步中,如果我注释掉printf,则返回我的程序;我得到的声明:

 age = 25 (it works!)
name = (null) (it works!)
!$h *tl J#@^&
name=null它可以工作!,在此更改中,后跟随机垃圾,表示指针地址错误

A注释掉的printf;语句在运行时不应该有什么不同,但在本例中确实如此。我的第一个想法是,我有一个指针问题,特别是当我试图使用间接运算符将结构文本的地址分配给指针b时

我看不出第2b步出了什么问题。我试着用几种方法修改它,但我得到了一个编译器错误。这就是我被卡住的地方——因为我遇到了一个逻辑错误

基于此程序思想的较大规模模型将有两个并集,由多个结构作为成员组成,因为每个结构将有多个不同数据类型的成员,即短整数、字符数组等,这些数据类型将作为参数传递给函数。同样的目标,只是扩大了


提前感谢。

如果您的编译器没有对您发出尖锐的警告,您可能没有打开足够的警告选项,或者您需要一个更好的编译器。不能将指针传递给某个联合的成员,就好像它是联合的一部分;除非忽略编译器的警告,否则不允许作弊——这几乎总是个坏主意

请注意,您的指针a和b没有初始化,因此取消对它们的引用会立即导致未定义的行为——幸运的话会导致核心转储,不幸运的话谁知道会发生什么

union combo_x *a, *b;
struct namedisc text;
struct id_num age;

age.idnumber = 25;
a->numtest = age;   // a is uninitialized - undefined behaviour

strcpy(text.name,"John Doe\0");
b->note = text;     // b is uninitialized - undefined behaviour
您可能会想到:

struct namedisc text;
struct id_num age;   
union combo_x *a = (union combo_x *)&text;
union combo_x *b = (union combo_x *)&age;

a->numtest.idnumber = age;
strcpy(b->note.name, "John Doe");
但是这些强制转换对于关闭编译器的合理抱怨是必要的

你可以合法地做的是:

union combo_x a;
union combo_x b;

a.numtest.idnumber = age;
strcpy(b.note.name, "John Doe");

首先,通过使用未初始化的a和b,或者通过将它们mallock或指向现有联合组合的地址,而不将它们指向任何有效的联合组合,会导致未定义的行为。如果编译器没有告诉您,请打开警告。见:

union combo_x *a, *b;

struct namedisc text;
struct id_num age;

age.idnumber = 25;
a->numtest = age; /* dereferencing a...where is a pointing? */

在这段代码中,变量a和b从未像它们应该的那样指向内存中的有效区域。在你描述的案例中,它是偶然起作用的

您应该将a设置为年龄变量的地址,而不是像现在这样尝试修改->numtest。b->note相同

换言之,让舒尔成为您代码中的一员:

a = &age;
b = &text;

这样,a和b都指向一个有效且分配的内存区域。

错误倾向的体现:顺便说一句,根据您对这里工作的理解程度,我不建议您使用纯C进行一个大型项目,尝试执行这种魔术。检查您的项目需求,也许更可取的做法是使用支持动态类型或多态性的语言。想想Python、Javascript和Java。有很多方法可以用更高级的语言创建大部分程序,并用C语言编写性能关键的部分。实际上,我的编译器是个问题——我需要安装一个新的。这就是解决方案,类型转换。我不能推荐类型转换解决方案;你在向你的编译器撒谎,当你这么做的时候,编译器往往会得到他们自己的回报。我同意,我以前的评论没有完全清楚地说明这一点。话虽如此,事实上,它可能会充分发挥作用。对你有利的一个因素是你有一个结构联盟。如果联合体中有一个普通的char*,理论上讲,你可能会遇到问题。FWIW,我在计算机ICL Perq上学习了C,其中内存位置地址的char*值不同于指向同一位置的任何其他指针类型。机器是字寻址的,奇数和偶数字节之间的差异编码在地址的高阶位,而不是低阶位。在这样的环境中,你得非常小心!我的编译器,以这样的方式抱怨,无法将int*转换为char*——其他时候我使用的是正确的类型,但生成了一个分段错误空指针赋值。这个计划奏效了。
a = &age;
b = &text;