原创

C语言结构体与联合体

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LS7011846/article/details/52626645

联合体

       C语言的联合体union又叫做共用体,并不常用,类似于大家所熟知的结构体struct。如其名,我们差不多能获知这个数据结构有一部分东西是共用的,结构里面除了变量空间,也没什么可以共用的了。即,共用体内部所有声明的变量,均为共用一个内存首址,联合体占用内存大小与联合体内部占用空间最大的变量相同。我们给其中每一个变量进行的赋值,都会影响到其他变量的值。下面直接砍一刀关于联合体的选择题。

#include <stdio.h>
int main()
{
    union
    {
        short int a[2];
        long b;
        char c[4];
    }s;
    s.a[0]=0x39;
    s.a[1]=0x38;
    printf("%lx %c\n",s.b,s.c[0]);
}
`</pre>

&#160; &#160; &#160; &#160;所以上面那道题的输出结果是?

&#160; &#160; &#160; &#160;3839 39?不对。

&#160; &#160; &#160; &#160;380039 39?不对。

&#160; &#160; &#160; &#160;答案是: 380039 9。 有点懵。

&#160; &#160; &#160; &#160;现在开始分析一下这道题,意图很明显,要考察联合体以及printf输出的格式符两个点。

&#160; &#160; &#160; &#160;short int 每个占两字节,两个四字节;long 占四字节;char 每个占一字节,四个占四字节。因此这三个变量所占据的内存空间大小一致,画了个草图如下:
![](http://i.imgur.com/JbpHnqx.png)

&#160; &#160; &#160; &#160;因此在对s.a进行赋值之后,联合体内部数据使用16进制表示为:

0x 0038 0039。而此时还应该注意的是char c[0]中存的是0x39,打印的是%c,即字符,所以打印出的字符不是0x39,而是0x39指向的ASCII码,即0x39=57,57对应字符9。所以,这道题打印出的结果是:

380039 9 。

# 结构体

&#160; &#160; &#160; &#160;关于C的结构体,我觉得我理解的还是不够深入,直接看一道题。  

<pre>`#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
struct A
{
int a;
char b [10];double c;
};
void f(struct A t);
int main()
{
struct A a={1001,&quot;zhang&quot;,1908};
f(a);
printf(&quot;%d,%s,%6.1f\n&quot;,a.a,a.b,a.c);
return 1;
}
void f(struct A t)
{t.a=1002;strcpy(t.b,&quot;chang&quot;);t.c=1201;}
`</pre>

&#160; &#160; &#160; &#160;进行过这样一番操作之后,结构体A的内容并没有变化,输出的结果与之前相同。这就让我当时觉得很费解的一个问题,为什么我传递进去结构体,而且修改了值,却实际内容没有变化?

&#160; &#160; &#160; &#160;其实,我在这里陷入了一个僵化的思维,在学习c之后,我接触了java,这段代码中的结构体,在java里面被视为内部类的存在,而A a相当于面向对象新建的对象,若是在java里面,对象作为函数的实参,此时传递的相当于对象的指针,指针在java中简化了。这样,函数中对形参对象的任何改变都会与实参同步改变。但需要注意的是,这里不是java,struct也不是对象。c语言中struct作为函数形参时,依旧是作为实参的一个副本,副本在子函数中再怎么改变,只要不return值,就不会影响到实参的值。  

## 指针的形参实参

&#160; &#160; &#160; &#160;这样根据上个题,就会想到通过函数参数传递,进行两个数交换的demo。使用的原理就是函数参数为指针,对两个指针中的数据内容进行交换,从而达到交换实参中的数据的目的。

正确的例子  

<pre>`void fun(int *p,int *q)
{
    int a;
    a = *p;
    *p = *q;
    *q = a;
}
`</pre>

错误的例子

<pre>`void fun(int *p,int *q)
{
    int *a;
    a = p;
    p = q;
    q = a;
}

       要注意的是,形参始终只是实参的一个副本,形参本身的变化,无法对实参的值造成影响。指针类型的形参与实参虽然不是一个变量, 但指向同一个地址;第一个函数,对形参指向的地址进行了数值变化;第二个函数,只是对形参的指向作了修改。

结语

       这些相关的题和知识都是计算机二级的很基础的计算机知识,我到现在却还需要重新复习一遍,学习态度是个问题。



正文到此结束
Loading...