c语言给结构体初始化赋值里的变量赋值有点奇怪?

c语言为什么结构体声明的时候可以直接赋值?

声明与后续赋值略有不同。在C语言中,有两种处理方法。如果定义了struct test{int a char c int b},则可以初始化struct test var={1,“c”,2}。结果是var.a=1,var.c=“c”,var.b=2。但是,如果随后分配var={1,“C”,2},则会报告一个错误。因为C语言不支持这种形式的操作。但您可以将其更改为var=(struct test){1,“C”,2}。在这种情况下,系统将应用一个临时变量,将其初始化为值,然后将一个值赋给var。C语言规则允许在相同类型的结构之间进行赋值操作。

c语言赋值语句正确写法?

(1)C的赋值语句具有其它高级语言赋值语句的功能。但不同的是:C中的赋值号“=”是一个运算符,可以写成a=b=C=D。在大多数其他语言中,赋值号不是运算符,上述书写是非法的。(2)

首先,我认为作为一个大学生,自学能力非常强。对于C语言没有学完的,可以花时间认真学习。不,你可以去图书馆查资料,或者上网,或者自学。现在网络平台有很多优质资源,你可以试试。第二,数据结构的算法是抽象的,必须认真研究。它是编程的基础,与C语言没有必然的联系。我们可以用C语言实现一些算法。它也可以用其他语言实现。

第三,对自己有信心。没有问题可以与老师和同学交流。既然我们选了一个好专业,就应该深入学习。

这是我的一些看法,希望对您有所帮助!

c语言结构体初始化赋值 c语言结构体变量赋值 结构体三种赋值方式

}

做个笔记,关于C语言中变量、数组、函数和指针间的关系:

引用一段作者hex108的精彩论述:

   一个内存地址存着一个对应的值,这是比较容易理解的。

   如果程序员必须清楚地知道某块内存存着什么内容和某个内容存在哪个内存地址里了,那他们的负担可想而知。
   汇编语法对“一个内存地址存着一个对应的数”,作了简单的“抽象”:把内存地址用变量名代替

了,对内存地址的取值和赋值方式不变。
   c语言对此进行了进一步的抽象:变量 <==> (一个内存地址,对应的值)(这里忽略类型等信息)。

   把C语言中的基本类型(int,long,float等),指针,数组等还原为(一个内存地址,对应的值)后,就能更清淅地理解它们了。

   为了下文的方便,特定义如下语义(遵循C的标准语义):

C语言中的变量一般具有带有两个性质,名字和值。当声明一个变量如

时,发生了两件事,一方面根据int,系统分配了(一般)2个字节的内存用以存放一个整数数值,另外设置了变量名表,加入了符号k和所分配的地址。之后遇到如

时,系统把k所对应的内存地址的置设置为2。所以我们说C语言的变量(例如名为var)具有一对特征值(内存地址addr,变量内容val)有时也分别称为(lvalue, rvalue)。lvalue在赋值号(=)左侧,而rvalue在赋值号右侧。一个变量名在赋值号左侧时表示地址,右侧时表示变量值。赋值语句val1 = val2,相当于左侧变量的地址内容设定为右侧变量的值。可以&var得到对应的地址addr,用*addr得到对应的内容va。内存中每一个字节具有一个地址,系统给不同类型变量分配的内存(称为一个memory cell)大小不同,如char型含有一个字节。而一个short型可能含有2个字节,一个long型可能含有4个字节。一个变量的地址定义为分配的内存区域的首字节地址。声明变量时要声明变量类型,相当于告知系统变量内存大小如何利用地址存取变量内容。系统为变量分配地址为一常数不可改变,但变量所存内容可以改变。

变量可以是结构体或数组。变量名是结构体或数组的首地址,即第一个元素的地址。变量内容也可以是另一个地址。这样的变量就是指针,如

其中int *声明p为int *型变量,即p的rvalue是可存储一个整型变量的内存地址。*p则表示p所指的内存区域的值 p也有地址,p的lvalue即&p就是p的地址。此处p尚未赋值,因此*p未知或错误,所以一般将未有指向的一个指针赋值为NULL,即指向0地址。而C语言的0地址具有特殊意义,不会被其他变量使用。指针的赋值使用

void型指针可以作为各类指针的一般性声明。

关于C语言数组首先注意两条:

(1)C语言只有一维数组,且数组大小必须在编译时作为常数确定下来,不过C99标准已经允许可变大小数组,在GCC编译器已经实现。C语言数组的元素可以是任意类型,因此可以是另一个数组,这样可以模拟出一个高维数组。

(2)对于一个数组,我们只能做两件事:确定数组大小,以及获得指向首个元素的地址的指针。其他关于数组的操作都是通过指针进行的。

C语言的数组为一顺序存储的线性表,在数组元素在内存中连续存储。数组名为数组的首地址,也就是第一个元素的地址。如:

此时p,a和&a[0]同为数组首地址。数组元素地址通过计算地址位移量(以数据类型存储空间为单位)取得,C语言的数组元素下标从0开始(后面所称第i个元素从第0个开始),使i等于位移量。指针和整数相加,整数自动按指针所指类型进行scale。p+i, a+i(i可以是负数)是第i号元素的地址(不是地址的二进制数值加i或者后面第i个内存位置)即&a[i]。*(p+i), *(a+i)就是第i号元素的值即a[i],即先计算元素地址,再取值。实际上C编译系统里a[i]就是*(a+i)的等价写法。因此,[]在这里可看成按位移量读取数值的运算符。所以此处指针变量也可带下标,p[i]与a[i]等价。因为a+i和i+a的含义一样,因此a[i]和i[a]含义一样。当i的值大于组大小时,以上各语句编译合法,但可能得到不可料的内存结果。指针和数组名不同之处在于1)因为p是指针变量,而a是数组地址(可以看作一个指针常量),所以p++合法而a++不合法。2)指针变量具有自己的存储空间。

指针的操作包括同类型指针赋值pa = pa;,指针加减整数p+i,p-j外,还包括同类型指针相减。q-p+1可以得到从p到q的特定种类的数据存储个数。这些操作一般要求在同一个数组内。

补充关于数组的初始化。1)数组在声明同时初始化时,数组大小不可为变量。2)全局数组和static数组,元素初始值为0,函数内定义的一般数组元素初始值不确定。

多维数组是元素也为数组的一维数组。以二维数组为例。如一个5行3列数组:

数组的元素存储先低维后高维。在C语言中数组的维数右侧为低维,左侧为高维(或称按行存储),而在Fortran中左侧维数为地位,右侧为高维(或称按列存储)。所以此数组a含有5个元素,每个元素是包含3个元素(而不是数组a包含3个各含有5个元素的数组型元素)的数组。a是指向指针数组的指针,它的值为首个元素数组的地址。a的元素是5个一维数组a[i](0<=i<=4)。所以a是第一元素的地址即a[0]的地址,(即a=a[0]=&a[0][0]),a+i就是第i个元素的地址,a[i]或*(a+i)第i个元素,因为他们是数组名,所以实际上也是地址

结构体作为一种变量类型,其地址就是结构体在内存中分配的空间的岂是地址。结构体类型指针可以指向结构体。如

注意*p两侧括号不可省。因为成员运算符.优先于*运算符。*p.num相当于*(p.num)。

C语言在编译时为定义的函数分配了一段存储空间,用来存储函数的指令。函数名就是所分配的内存起始首地址(入口地址)。可以定义指向函数的指针。

注意第三行代码的*p两边的括号不能少,否则变成声明返回值为指针类型的函数p。函数型指针也可以作为函数的参数。

这段代码是非法的(但在的编译器是可以通过的!但意义不同: *p为数值,p[3]实际上是a[0][3]),因为p是指向整型变量的指针。而a是指向整型数组的指针。故需要声明p为指向整型数组的指针:

七、指向指针的指针。注意以下两个声明的不同:

前者是二维数组,a和a+i的类型为char (*)[6],a的每个元素是(大小为6的)字符数组。a[i]的类型是char *,是字符的存储地址,a[i][j]则是字符,整个数组a存储在动态存储区 。而后者的是指针数组,b和b+i的类型是char **,他的每个元素b[i]是字符指针(指向字符串常量),b的5个指针元素位于动态存取区,而每个元素指向连续存储在静态存储区的字符串常量。

所以指向a的指针应该是char (*)[6]型,而指向b的指针应该是char **型:

八、数组作为函数的形式参数。

当声明数组作为函数的形式参数时,等价于声明数组名为指针,即数组名是不再是指针常量而变成指针变量。因为函数的形式参数是需要接收实参的值,这里是数组的首地址,而纯粹的数组名是不能进行赋值的。下面几个函数:

完全等价。在这几个函数中可以对a进行指针操作。

(1)一个变量有地址和值。一个变量可以占有多个内存空间,它的地址就是内存的起始地址。

(2)变量的值可以是规定类型的地址,这就是指针。通过指针可以对其指向的变量进行操作。

(3)多个同型变量构成一个数组。数组在内存中顺序存储,数组名是数组首地址能。

(4)指针的操作同类型指针赋值、指针加或减整数(根据指针类型自动scale)和同数组内的指针相减。

(5)函数名是函数指令所分配空间的起始地址(?)。

(6)可以定义指向数组的指针(如char (*p)[N];) 和指向指针的指针(如char **p;)。

(7)当数组作为函数的形式参数时,数组名作为指针处理。

部分内容是我个人的理解,或有错误。

【1】 谭浩强著. C程序设计(第四版). 北京:清华大学出版社,2010

}

当我们将一个程序交给CPU去执行的时候,CPU只会执行main函数中的代码,别的地方的代码是不会执行的,因此如果想要在CPU中执行程序就必须要在main函数中从上到下一句一句执行代码,并且只有在上一句执行完毕之后才会执行下一句。
mian是程序的入口,当mian函数中的代码执行完毕之后就会自动结束,所以也是出口。

CPU : 中央处理器,处理数据的,负责计算,协调其他硬件相互和谐的工作。

内存 :存储数据 ,临时,效率高,通过电路存储,电子式。

硬盘 :存储数据 ,永久存储,效率低,效率和转速有关,机械式。

3. 程序是如何运行的

程序本质就是一对指令,程序存储在硬盘之中,当双击点开之后,CPU会先将程序复制到内存之中,然后CPU再去读取内存中程序的指令。这是因为在内存中CPU的读取效率更高。
例如:播放器播放电影,播放时是运行在内存中的,但是电影文件确实保存在硬盘中的,当双击电影打开播放器,播放器运行在内存中,然后播放器在去分段的读取电影文件。

或者英雄联盟这样的大型游戏也不是将整个游戏拷贝到内存中,而是只将exe文件拷贝到CPU中,然后需要什么文件就加载哪些文件,不用的就会释放掉。

    程序自己是否要把这些数据存储起来,对于用户操作产生的数据,或者一会儿要用的数据可以存储起来,以便以后显示方便快捷。 存储到内存中,因为程序自己就在内存当中
  1. 如何将数据存储在内存之中?
    先在内存中找一个位置,将数据放到这个位置中,当想要使用数据的时候,只要找到这个位置就可以了。
    而每一个位置在内存中都有一个独一无二地址,16进制表示,0x开头。通过这个地址找到这个位置,然而地址非常难记,所以给位置起个别名,通过别名找到位置。
    因此在开辟空间的同时,需要指定空间的别名和类型,而变量就是内存中用来存储数据的空间,那么变量名就是变量所代表的那块空间的别名。所以,变量的本质就是内存中存储数据的那块儿空间。
    声明一个变量,实际上就是在内存中开辟一块指定类型和别名的空间

5. 内存中的五大区域

为什么要分区个区域?虽然每一个区域都是用来存储数据的,但是不同的数据存储在不同的区域,这样不仅方便系统的管理,也可以使系统更快,更明确的找到要找的地址。

  1. 栈 - 专门用来存储局部变量,所有的局部变量都是声明在栈区域当中。
  1. 堆 - 允许程序员手动的从堆申请空间来使用。程序员可以自己申请指定字节数的空间。
  2. BSS段 - 用来存储未初始化的全局变量和静态变量,声明一个全局变量,如果我们没有初始化,在程序运行最开始的时候,这个变量没有初始化时是存储在BSS段,初始化之后,全局变量和静态变量就会被放到常量区。
  3. 数据段/常量区 - 用来存储已经初始化的全局变量、静态变量,还有常量数据
  4. 代码段 - 用来存储程序的代码/指令。

注意:我们堆中申请的字节空间,如果我们不主动释放,那么系统是不会释放的,除非程序结束
如何在堆区申请指定字节数的字节空间呢?C语言提供了三个函数用来申请空间。这三个函数声明在<stdlib.h>的系统头文件中。

表示在堆内存中申请参数个连续的字节空间,返回值是void *表示没有类型的指针。并且返回的是创建的空间中的第一个字节的地址。
那么我们应该使用什么类型的指针变量来保存malloc()返回的地址?
用什么类型去接受,那要看你想要如何去操作申请的这些字节空间。如果你想要4个字节4个字节去操作那么就要用 int * 类型去接收,如果想8个字节8个字节的去错做那么就用 double * 类型去接收。

所以: int *p = malloc(24); 就相当于在堆内存中创建了一个长度为6的整型数组

1.在堆区申请的字节空间是从低地址向高地址申请,每次申请的字节地址都是从0开始的,并且每次申请的空间不一定是连续的。但是每一次申请的指定个字节,这些字节一定是连续的。
2.在堆区申请的字节里面也是有值的,值是垃圾值,并且值不会自动清零。
3.在向堆区申请字节空间的时候,有可能会申请失败,如果申请失败,返回的指针就是NULL值,所以我们在申请空间之后,最好进行判断 if(p1) 看是否申请成功。
4.申请的空间使用完毕之后,一定要进行释放 free(p1); 如果没有free(),那么需要等程序结束之后这些空间才会被释放。

calloc() 作用:向堆区申请指定字节数的空间。
参数2.每一个单位的字节数
同样有可能申请失败。与malloc()的优势,calloc()申请的字节,申请完之后,系统会将申请到的空间自动清零

当我们申请的字节空间不够用的时候,我们可以使用realloc() 扩容。
一般会在我们申请的空间后面扩容,但是如果我们申请的空间后面被占用了,或者不够我们扩容的空间,就会重新去寻找一块新足够的空间申请,并将原来的数据拷贝过来,原来的空间将被释放。

注意:我们只能操作我们申请到的字节空间,如果贸然操作其他字节空间,很有可能修改掉系统的数据,造成严重问题。

作用: 将字符串数据输出到指定的流中。
流: 标准输出流->控制台。文件流 --> 磁盘上的文件。
使用格式: fputs(要输出的字符串,指定的流);
1). 使用fputs函数将字符串数据输出到标准输出流,也就是控制台
2). 将字符串存储到文件中.
a. 要先声明1个文件指针,指向磁盘上的文件。使用fopen函数可以创建1个指向文件的指针。

fopen函数的两个参数:
第1个参数: 文件的路径,代表创建的指针就指向这个文件。
第2个参数: 操作文件的模式,你要对这个文件做什么操作,必须要告诉他。
当操作模式是"w"的时候,如果文件不存在, 就会创建这个文件,如果文件存在,就会将原来的文件替换掉。
当操作模式是"a"的时候,如果文件存在则追加。如果不存在就创建这个文件。

b. 使用fputs函数将字符串写入到指定的文件流中。
c. 写完之后,一定要记得使用fclose()函数将这个文件关闭。

作用: 从指定的流中读取字符串。
这个流可以是标准输入流-->控制台,也可以是文件流。
1). 使用fgets函数从标准输入流中读取数据。
使用fgets函数从控制台接收用户输入字符串,scanf函数gets函数也可以实现这个功能。

b. 输入的空格会被认为结束. b. 空格也会一并接收.
fgets(要将字符串存储到哪1个数组中,最多接收多少个长度的字符串,指定流);
第2个参数: 如果参数为n 那么函数最多就接收n-1个长度的字符串,这个参数一般情况下和第1个参数数组的长度一致。
第3个参数:流,stdin: 代表标准输入流,也就是键盘流从控制台输入。

为什么fgets函数是安全的?
1. 如果输入的字符串的长度大于等于了第2个参数n,只会接收前面的n-1个,然后最后1个自动是'\0'。这样,就不会崩溃。
2. 如果输入的字符串的长度刚好等于n-1那就是刚好的。
3. 如果输入的字符串的长度小于了n-1,那么就会将我们最后输入的换行字符'\n'一并的接收。然后后面才是'\0'结束符。

2). 使用fgets函数从文件流中读取数据:

就是读取磁盘上文件的内容.
// 1. 创建1个读取文件的文件流.
// 2. 准备1个字符数组.准备存储读取到的字符串数据.
// 3. 使用fgets函数从指定的文件流中读取.

8. const修饰基本数据类型的变量

const是1个关键字,是来修饰变量的,也就是说在声明变量的同时,可以使用const关键字来修饰。
一般情况下来说,被const修饰的变量具备一定程度上的不可变性,被const修饰的变量我们叫做只读变量。

这个时候.num变量的值只能去取值,而不能去修改. 数组的元素的值不能修改. 无法通过p1指针去修改指针指向的变量的值,但是如果直接操作变量这是可以的,并且指针变量的值可以改,可以把另外1个变量的地址赋值给这个指针。 p1的值不能修改,但是可以通过p1去修改p1指向的变量的值。 既不能修改p1的值,也不能通过p1去修改p1指向的变量的值。 被const修饰的变量,是只读变量,只能取值而不能改值。所以,const变量的值,至始至终都不会发生变化。因此当某些数据是固定的,在整个程序运行期间都不会发生变化,并且你也不允许别人去修改时,可以使用const来修饰这个变量。 3. 当函数的参数是1个指针的时候,函数的内部是有可能会修改实参变量的值的,那么这个时候,可以使用const修饰指针参数,这样函数内部只会使用我们的值

不同的数据类型的变量是用来保存不同类型的数据的。而结构体是我们自己定义的数据类型。并指定这个数据类型的变量由哪些小的变量和成的。

这代表我们新创建了一个数据类型,这个数据类型的名称叫做 struct Student
这个新类型是由1个char * 类型,一个int 类型,一个float类型的小的标量联合而成的。然而只有类型是不够的,还需要根据类型声明变量。

声明结构体类型的变量:

** 结构体变量的初始化**
意义:为结构体变量中的小变量赋值。严格意义上是将地址赋值给小变量。结构体变量中的小变量就叫做结构体的成员。

初始化语法 使用点语法。
结构体变量名称.成员 = 数据;

当要保存一个数据,但是发现这个数据需要由其他小变量组成的,这个时候先使用结构体类自定义这个数据类型由哪些小变量合成的,然后在根据这个结构体类型声明变量,来保存数据。

  1. 一定要先声明结构体类型,然后在声明结构体变量。

  2. 结构体变量也是变量所以可以批量声明。

  3. 定义结构体名称要求每一个单词的首字母大写。

  4. 可以在声明结构体类型的时候声明结构体变量。

  5. // 匿名结构体只能在声明结构体的同时创建变量,并且不能单独的声明变量
  1. 先声明变量,在使用点语法一个一个赋值。
  2. 在声明结构体变量的同时,就为结构体变量的成员初始化。(最常用)
  3. 只初始化部分成员,按顺序。

结构体变量成员的默认值
声明一个结构体变量,如果没有给结构体变量成员赋值,那么成员是有值的,是垃圾值。只要在声明结构体变量的同时,为一个成员变量初始化,整个结构体就会自动初始化为0,就不在是垃圾值了。

一般情况下结构体类型都是定义在函数外面,已让所有函数都可以使用。

结构体变量之间的相互赋值
相同结构体类型的结构体变量是可以赋值的。
结构体变量之间赋值的原理:
将结构体变量中的每一个成员的值,拷贝过来复制一份,然后重新赋值给目标结构体变量中对应的成员。结构体变量之间的赋值是值传递。

struct 结构体类型名称 数组名[数组长度]; 
可以存储5个strut 结构体类型名称 的结构体
或者直接在声明结构体数组的时候,为结构体赋值。
使用sizeof计算出数组占用的总字节数/ 每一个元素占用的字节数
声明了一个pStu指针变量,这个指针变量的类型是struct Student *。

使用。可以使用指针间接的访问结构体变量。

(*结构体指针名).成员 结构体指针名->成员

结构体是可以嵌套的,在一个结构体内部声明另外一个结构体即可。

结构体是自定义的数据类型,当然可以作为参数,结构体作为参数传值是值传递,如果想要在函数中修改结构体变量的值,可以使用结构体指针。

结构题类型完全可以作为函数的返回值,在返回的时候直接将结构体变量返回即可。如果返回结构体变量的地址,需要将结构体创建在堆区。

变量的取值只能是指定的几个值当中的任意一个,除此之外其他不行,需要自己定义具备限定取值的类型。
作用:支持先创建一种数据类型,这个数据类型的变量的取值被限定。

这个数据类型的名称叫做 **enum Type **。可以声明这个类型的变量,这个变量中就只能存储这其中指定的任意一个。

enum 枚举类型名称 变量名 = 枚举类型限定的取值之一。

一般定义在函数外,每一个枚举值都对应一个整形数,默认为0,依次递增。枚举类型的变量,无论什么类型 都占据4个字节。而枚举变量中真正存储的是,枚举值对应的整形的数。所以使用%d输出枚举的值。

所以也可以直接为枚举变量赋值整形变量。但是一般不建议这么做 ,可读性降低。命名规范 首字母大写,每一个单词的首字母大写
枚举值名称以枚举类型名开头

作用: 为一个已经存在的数据类型取别名。
因此当数据类型很长的时候既可以为这个数据类型取一个短一点的别名。

1.声明结构体类型的同时给结构体区别名 2.最常用是为声明匿名结构体的同时 取一个短别名。

C语言从编写到编译、链接、执行的流程

  1. 先执行原文件中的预处理指令,如果有文件包含指令,就将文件的内容拷贝到写指令的地方。
  2. 检查语法是否符合规范,符合就生成.o目标文件,就是.c 对应的二进制指令。如果不符合语法规范,就报错不生成.o目标文件。为.o的目标文件添加启动代码
    告诉编译器要调用的函数在什么地方
    调用的时候去正确的地方找实现
  3. 链接成功以后.out文件运行即可。

预处理指令以#开头,并且都是在编译之前执行。

  1. 宏定义:可以将一段代码定义为一个标识,使用这个标识就代表这段代码。
  2. 条件编译指令:只编译指定的C代码为二进制指令。

会将C代码中使用宏名的地方替换成宏值 过程叫做宏替换

宏值可以是任意语句,定义宏的时候,并不会去检查与法,只有当完成了宏替换的时候,才会去检查替换以后的代码是否符合语法规范。
如果宏值是一个表达式,那么宏值并不是表达式的值,而是表达式本身。
如果宏值当中包括一个变量名,那么在使用这个宏之前必须保证这个变量已经存在。
无法通过赋值符号位宏赋值。因为宏根本就不是变量。

从定义宏的地方开始,后面的所有地方都可以使用这个宏。就算这个宏定义在这个大括弧里面,在这个后面,哪怕是大括弧的后面都可以使用。
默认情况下,宏从定义的地方一直到文件结束都可以使用,#undef可以让宏提前失效

解除宏定义,之后宏就不可以使用了 体现实效

字符串优先,也就是字符串中不会识别宏。系统不会认为是一个宏,而认为是字符串的一部分。
宏的层层替换。一个宏值中可以使用另外一个宏名。

#define 预处理指令 在预编译的时候会把宏明替换成宏值,typedef运行的时候才会执行。
#define可以将任意的C代码取一个表示名, typedef只能为数据类型取名字。

在定义宏的时候,宏名是可以带参数的。在这个宏值当中,可以直接使用这个参数。

// 如果使用的宏有参数,就必须在使用的时候为宏传值。

先将参数赋值,然后在将宏值里面用到参数的地方替换为值,最后宏替换,将值替换为宏名。

  1. 宏不是函数,所以宏的参数不需要添加类型说明。
  2. 我们在定义宏的时候,编译器是如何区分宏名和宏值的。
    #define 宏名 宏值 宏名中不可以有空格,与参数之间也不可以有空格。
  3. 为带参数的宏传值的时候,是本色传递,如果传递一个变量,并不是传递这个变量的值,而是直接传递的就是这个变量的串。
  4. 宏值一旦换行就认为宏定义结束了,需要使用 \ 来拼接宏
  5. 宏只适合于少量的代码。
  1. 预处理指令, 在预编译阶段执行。
  2. 作用:默认情况下,我们所有的C代码都会被编译为二进制代码,条件编译指令的作用,可以让编译器只编译部分的代码。
  1. 条件编译指令是一个预处理指令,在预处理阶段执行,而if语句是C代码,在程序运行的时候执行。
  2. if语句无论如何全都要被编译为二进制指令,条件编译指令:只会将符合条件的C代码编译为二进制指令。
  3. 条件编译指令参数必须为宏。
如果定义了宏名的宏 就编译其中的代码 如果没有定义宏名就来到这里。

C语言当中的两个关键字,是用来修饰变量和函数的。
如果都没有修饰 默认是 extern 。

  1. static修饰局部变量,那么这个变量就叫做静态变量,静态变量不在存储在栈区,而是存储在常量区中,当函数执行完毕之后,这个静态变量不会被回收。
    当第一次执行这个函数的时候,就会将这个静态变量声明在常量区,第二次去执行这个函数的时候,声明静态变量的这句话就不会在执行了,而是直接略过,直接使用静态变量的值。
    所以static修饰的静态变量,函数结束不会被回收,仍然存在,函数无论执行多少次,这个静态变量只有一份。
    extern不能修饰局部变量。

  2. 一个全局变量,最完整的步骤也应该分为两步,1.先写全局变量的声明,只定义而不赋值。2.在写全局变量的定义,定义全局变量并初始化。
    全局变量可以只有声明,如果这样的话,那么这个全局变量的值背会编译器自动的去实现,会将这个全局变量自动初始化为0。
    全局变量也可以只有定义而没有声明,但是这个时候,这个全局变量的定义必须要在使用全局变量的函数的前面。
    全局变量的声明要写在.h文件中,全局变量的实现要写在.c文件中。
    如果将全局变量定义在模块之中,这个全局变量就必须要使用static或者extern来修饰
    static修饰全局变量,这个全局变量只能在当前 模块访问。
    extern修饰全局变量,这个全局变量就可以跨模块访问。

  3. static修饰函数 函数只可以在当前模块访问
    extern修饰函数 那么函数可以跨模块调用

文中如果有不对的地方欢迎指出。我是xx_cc,一只长大很久但还没有二够的家伙。

本文已在版权印备案,如需转载请访问版权印。

}

我要回帖

更多关于 结构体初始化赋值 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信