我是大甲鱼 发表于 2018-8-22 23:40:12

结构体指针做形参,实参可用结构体数组访问??

本帖最后由 我是大甲鱼 于 2018-8-22 23:42 编辑

#include <stdio.h>
typedef struct ex
{
        int a;
        int b;
}ex,*p_ex;

void fun(p_ex temp);
ex msg;
int main()
{       
        msg.a=2;
        printf("befor msg.a=%d\n",msg.a);//msg.a的值
        printf("&(msg.a)=%p\n",&(msg.a));//msg.a的地址

        fun(&msg);//经过函数处理msg.a的值被函数中的temp.a=3;改变

        printf("after msg.a=%d\n",msg.a); // 为什么msg.a会被temp.a改变呢?可能是他们的地址是一样的

        //可是为什么temp.a temp.a可以被赋值,又应该怎么用temp来访问??
        putchar('\n');
        return 0;
}
void fun(p_ex temp)
{
        printf("-------------对应值---------------\n");
        temp->a=1;
        printf("temp->a=%d\n",temp->a);

        temp.a=3;
        printf("temp.a=%d\n",temp.a);

        temp.a=4;
        printf("temp.a=%d\n",temp.a);

        temp.a=5;
        printf("temp.a=%d\n",temp.a);

        temp.b=6;
        printf("temp.b=%d\n",temp.b);

        temp.b=7;
        printf("temp.b=%d\n",temp.b);

        temp.b=8;
        printf("temp.b=%d\n",temp.b);
        printf("-------------对应地址---------------\n");

        printf("&(temp->a)=%p\n",&(temp->a));
        printf("&(temp->b)=%p\n",&(temp->b));
        printf("&(temp.a)=%p\n",&(temp.a));
        printf("&(temp.b)=%p\n",&(temp.b));
        printf("&(temp.a)=%p\n",&(temp.a));
        printf("&(temp.b)=%p\n",&(temp.b));
        printf("&(temp.a)=%p\n",&(temp.a));
        printf("&(temp.b)=%p\n\n",&(temp.b));
}


运算结果:
befor msg.a=2
&(msg.a)=00427E60
-------------对应值---------------
temp->a=1
temp.a=3
temp.a=4
temp.a=5
temp.b=6
temp.b=7
temp.b=8
-------------对应地址---------------
&(temp->a)=00427E60
&(temp->b)=00427E64
&(temp.a)=00427E60
&(temp.b)=00427E64
&(temp.a)=00427E68
&(temp.b)=00427E6C
&(temp.a)=00427E70
&(temp.b)=00427E74

after msg.a=3

Press any key to continue

我是大甲鱼 发表于 2018-8-22 23:41:28

为什么不能本地上传图片 ??

claws0n 发表于 2018-8-22 23:46:25

我是大甲鱼 发表于 2018-8-22 23:41
为什么不能本地上传图片 ??

进入高级模式

我是大甲鱼 发表于 2018-8-23 00:12:23

claws0n 发表于 2018-8-22 23:46
进入高级模式

不管他什么模式了,大佬知道这是我为什么吗

claws0n 发表于 2018-8-23 00:20:14

当然可以换 *p_ex 与 ex 是属于同一个结构体
没错,因为地址一样,所以被改变了
第二个情况没有遇过,不过这样写是很危险的。结构体本身就可大可小,也许是因为这样,所以编译器让你自由扩充结构体的空间。
可以赋值就可以直接访问了 int a= 3; printf("%d", a) == 3

我是大甲鱼 发表于 2018-8-23 00:40:06

claws0n 发表于 2018-8-23 00:20
当然可以换 *p_ex 与 ex 是属于同一个结构体
没错,因为地址一样,所以被改变了
第二个情况没有遇过,不 ...

(temp+0)->a==temp.a    (temp+1)->a==temp.a   (temp+2)->a==temp.a
(temp+0)->a==temp.a的地址相同可以理解为什么可以赋值。感觉传进来的结构体指针变成了一个结构体数组。我是在学嵌入式的时候看到这种写法,看了好久没看懂。百度也不好描述。
typedef struct i2c_msg {
        unsigned int addr;/* 7bits   地址*/   
        int flags;/* 0 - write, 1 - read */
        int len;                //数据长度
        int cnt_transferred;
        int err;
        unsigned char *buf;                //存数据
}i2c_msg, *p_i2c_msg;

int s3c2440_master_xfer(p_i2c_msg msgs, int num)
{
        int i;
        int err;
       
        for (i = 0; i < num; i++)       
        {
                if (msgs.flags == 0)/* write */
                        err = do_master_tx(&msgs);
                else
                        err = do_master_rx(&msgs);
                if (err)
                        return err;
        }
        return 0;
}


老铁早些睡觉吧

claws0n 发表于 2018-8-23 10:53:31

我是大甲鱼 发表于 2018-8-23 00:40
(temp+0)->a==temp.a    (temp+1)->a==temp.a   (temp+2)->a==temp.a
(temp+0)->a==temp ...

{:10_245:} 嵌入式,还没学过{:10_282:}
呼叫大神 @无符号整形
程序透过结构体指针改变结构体内容,但是代码 24 - 46 对结构体扩充
我的回答: 5 楼

无符号整形 发表于 2018-8-23 11:09:23

本帖最后由 无符号整形 于 2018-8-23 11:21 编辑

见9楼

无符号整形 发表于 2018-8-23 11:21:02

claws0n 发表于 2018-8-23 10:53
嵌入式,还没学过
呼叫大神 @无符号整形
程序透过结构体指针改变结构体内容,但 ...

总算明白你要问什么了。
temp就相当于*(temp+0),相当于temp
temp就相当于*(temp+1),相当与temp的下一个地址
以此类推

claws0n 发表于 2018-8-23 11:29:55

无符号整形 发表于 2018-8-23 11:21
总算明白你要问什么了。
temp就相当于*(temp+0),相当于temp
temp就相当于*(temp+1),相当与temp ...

对这个线性扩充我知道,所以
第二个情况没有遇过,不过这样写是很危险的。结构体本身就可大可小,也许是因为这样,所以编译器让你自由扩充结构体的空间。
但是没有相对应的结构/变量,很危险,算野指针?

无符号整形 发表于 2018-8-23 11:33:43

claws0n 发表于 2018-8-23 11:29
对这个线性扩充我知道,所以

但是没有相对应的结构/变量,很危险,算野指针?

无符号整形 发表于 2018-8-23 11:36:50

claws0n 发表于 2018-8-23 11:29
对这个线性扩充我知道,所以

但是没有相对应的结构/变量,很危险,算野指针?

那个地方如果是栈的话可能会超过栈顶,有可能超过栈底。假如是内存的话可能会访问到别的进程的地址空间,甚至有可能访问到系统内核保留空间(0x70000000~0xFFFFFFFF),这样会引发0xC000005错误,就是访问违规,会导致程序“停止工作”。(其实你可以通过try来捕获这些异常但是扯太远了)

claws0n 发表于 2018-8-23 11:42:29

无符号整形 发表于 2018-8-23 11:36
那个地方如果是栈的话可能会超过栈顶,有可能超过栈底。假如是内存的话可能会访问到别的进程的地址空间, ...

甚至有可能访问到系统内核保留空间(0x70000000~0xFFFFFFFF),这样会引发0xC000005错误,就是访问违规,会导致程序“停止工作”。可以理解,数字认不得~
(其实你可以通过try来捕获这些异常但是扯太远了){:9_241:}
初学者{:10_282:}

lichuncheng 发表于 2018-8-23 11:48:37

{:10_277:}啦啦啦啦啦啦

我是大甲鱼 发表于 2018-8-23 13:08:54

无符号整形 发表于 2018-8-23 11:21
总算明白你要问什么了。
temp就相当于*(temp+0),相当于temp
temp就相当于*(temp+1),相当与temp ...

1.当传入的是一个结构体地址的时候可以用temp->a访问也能用temp.a访问,但是超出后可能会发生一些严重的错误。
2.当传入的是一个结构体数组的地址,在这个数组元素个数范围内都可以用temp.a来访问


这样理解对么?

无符号整形 发表于 2018-8-23 14:14:49

我是大甲鱼 发表于 2018-8-23 13:08
1.当传入的是一个结构体地址的时候可以用temp->a访问也能用temp.a访问,但是超出后可能会发生一些严 ...

对的

无符号整形 发表于 2018-8-23 14:19:48

本帖最后由 无符号整形 于 2018-8-23 14:21 编辑

claws0n 发表于 2018-8-23 11:42
甚至有可能访问到系统内核保留空间(0x70000000~0xFFFFFFFF),这样会引发0xC000005错误,就是访问违规, ...

try//尝试执行的语句部分
{
        ...
}
catch(xxx xx)//假如出现了异常,系统会抛出一个异常结构,这个结构是不确定的,你需要根据上面的可能会出现的错误来决定
{
        ...
}

PS:什么?你是初学者??我不信~别那么谦虚嘛~{:10_277:}
页: [1]
查看完整版本: 结构体指针做形参,实参可用结构体数组访问??