日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

C语言:随笔4

發布時間:2023/11/27 生活经验 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言:随笔4 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、函數形參和實參的說明:

(1)在定義函數時指定的形參,在未出現函數調用時,他們并不占內存中的存儲單元。只有發生函數調用時,函數中的形參才被分配內存單元。在調用結束后,形參所占的內存單元也被釋放。

(2)實參可以是常量、變量或表達式,如:max(3,a+b);但要求他們有確定的值。在調用時將實參的值賦給(是賦值給)形參。

(3)在被定義的函數中,必須指定形參的類型;

(4)實參與形參的類型應相同或者賦值兼容。

(5)在C語言中,實參向形參的數據傳遞是“值傳遞”(相當于COPY)單向傳遞,只由實參傳給形參,而不能由形參傳回來給實參。在內存中,實參單元與形參單元是不同的。

PS:在調用函數時,給形參分配存儲單元,并將實參對應的值傳遞給形參,調用結束后形參單元被釋放,實參單元仍保留并維持原值,因此在執行一個被調用函數時,形參的值如果發生改變,并不會改變主調函數的實參的值。(如果要發生改變,我們后期會使用一個傳址,此處是地址的址,就會改變他的內存,就是傳過去的是地址或者引用)(現在是傳值,只是copy,數值的值)

2、函數的返回值:

(1)函數的返回值是通過函數中的return語句獲得的;

return語句將被調用函數中的一個確定值帶回主調函數中去。

一個函數中可以有一個以上的return語句,執行到哪一個return語句,哪一個語句起作用。

return后邊可以是一個值也可以是一個表達式,只要你這個表達式最后能夠算出一個確切的值那就ok了。

在C語言中凡是不加類型說明的函數,自動按照整型處理。

3、函數聲明的作用;

聲明的作用是把函數名、函數參數的個數和函數類型等信息通知編譯系統,以便在遇到函數調用時,編譯系統能正確識別函數并檢查調用是否合法。(例如函數名是否正確,實參與形參的類型和個數是否一致)

函數的“定義”和“聲明”不是一回事,函數的定義是指函數功能的確立。包括函數名、函數值類型、形參及其類型、函數體等,他是一個完整的、獨立的函數單位。(所以函數聲明是不占內存的,他的定義是占內存的)

如果函數定義出現在主調函數之前,可以不必加以聲明。

C語言不能嵌套定義函數,但是可以嵌套調用函數。

4、遞歸

在調用一個函數的過程中又出現直接或間接的調用該函數本身,稱為函數的遞歸調用。

5、數組作為函數參數。

數組可以作為函數的參數使用,進行數據傳送數組用作函數參數有兩種形式:

(1)一種是把數組元素(下標變量)作為實參使用。

數組元素就是下標變量(a[1]就是第二個元素),他與普通變量并無區別,因此,他作為函數實參使用與普通變量是完全相同的,在發生函數調用時,把作為實參的數組元素的值傳送給形參,實現單向的值傳遞。

(2)另一種是把數組名作為函數的形參和實參使用。

PS:用數組名作函數參數與用數組元素做實參有幾點不同:

1):用數組元素做實參時,只要數組類型和函數的形參變量的類型一致,那么作為下標變量的數組元素的類型也和函數形參變量的類型是一致的,因此,并不要求函數的形參也是下標變量。即對數組元素的處理是按普通變量對待的。

2)用數組名做函數的參數時,則要求形參和相對應的實參都必須是類型相同的數組,都必須有明確的數組說明,當形參和實參二者不一致時,即會發生錯誤。

為什么如果是傳遞數組名的化,他的實參和形參都必須是數組?

數組名其實就是一堆數組變量的第一個元素的地址,領頭羊的地址,相當于指針,指針變量里邊存放的也是一個地址。

3)在普通變量或下標變量做函數參數時,形參變量和實參變量是由編譯系統分配的兩個不同的內存單元。在函數調用時發生的值傳遞是把實參變量的值賦予形參變量。

在用數組名做函數參數時,不是進行值的傳送(而是進行(地址)傳遞),即不是把實參數組的每一個元素值都賦予形參數組的各個元素。

為什么呢?

因為:實際上形參數組并不存在,編譯系統不為形參數組分配內存單元。(那為什么之前我們說實參變量把他變成一個元素的時候他就可以為它分配單元,而把它當作地址的化它就不分配內存呢?)

那么數據的傳送是如何實現的呢?

在此之前介紹過,數組名就是數組的首地址。因此,在數組名作為函數參數(實參)時所進行的傳送只是地址(數組的第一個元素的地址)的傳送(把他第一個元素的地址傳過去),也就是說把實參數組的首地址賦予形參數組名。(那這樣的話,他就沒有必要把整個數組都傳過去,因為等一下拿到地址之后我就知道他在那里了,我直接拿來用就行了)

形參數組名取得該首地址之后,也就等于有了實在的數組(相同的數組)。實際上是形參數組和實參數組為同一數組(因為他們指向同一段內存空間),共同擁有一段內存空間。

#include<stdio.h>void test(int b[10])
void main()
{int a[10]={2,4,6,8};//數組的地址的連續的test(a);//傳一個地址過去,因為數組名就是數組的首地址putchar("\n")
}
void test(int b[10])//int一個 b數組接收到地址,可以說b數組也是指向了首地址
{int i=0;for(;i<10;i++){printf("%d",b[i])//再打印}
}

見下圖存放:

5、1形參數組不定義長度

就是把上邊的b不定義長度,說明你只要定義他是一個數組類型跟編譯器說他是一個數組類型那就ok了,你不用給他說這個數組有多大,因為編譯器他根本不會再定義一個數組出來,他只是指向了原來的數組,原來的數組有多大,他就有多大。(或者你也可以寫array[2]或者array[20]都行,他只是把他指向了a數組,并沒有重新定義一個新的數組。)

#include<stdio.h>void test(int array[])//不給他一個大小
void main()
{int a[10]={2,4,6,8};//數組的地址的連續的test(a);//傳一個地址過去,因為數組名就是數組的首地址putchar("\n")
}
void test(int array[])//array不定義長度int i=0;for(;i<10;i++){printf("%d",b[i])}
}

6、形參也是局部變量(局部變量存放在棧中)。(函數中的變量調用完之后就會自動銷毀,但是全局變量的化必須等整個程序完全中止才會結束。(不同函數中可以使用同一個局部變量名,雖然他們是名字一樣但是不同的內存空間的。)

變量的存儲類別:

6.1變量的存儲類別

大家知道從變量的作用域(即從空間)角度來分,可以分為全居變量(作用域不同全局變量的作用域是整個文件)和局部變量(局部變量的作用域是整個函數)。那么從變量值存在的時間(即生存期)角度來分又可以分為靜態存儲方式和動態存儲方式。

關鍵字auto可以省略,auto不寫則隱含定為“自動存儲類別”,屬于動態存儲方式。

有時候函數中的局部變量的值在函數調用結束后不消失而保留原值,即其占用的存儲單元不釋放,在下次該函數調用時,該變量已有值就是上次函數調用結束時的值。這時就應該指定該局部變量為“靜態局部變量”,用關鍵字static進行聲明。

下邊例子進行說明:

#include <stdio.h>
int f(int a)//a傳給它的是2//相當于a=2賦值過去(兩個a在不同的函數,位置不同,此處的a你定義為d也可以將main函數中的a傳過來的)
{auto int b=0;//局部變量存放的是在棧這個位置,static int c=3;//而靜態變量存放在數據區這個位置b=b+1;//b==1,1,1c=c+1;//c==4,5,6return(a+b+c);//返回3次7,8,9(第二次調用f函數的時候,b重新賦值為0(因為b不是static型),而c因為是static是靜態的,上一次函數調用完之后沒有銷毀保留了第一次的4,所以第二次加1就是5)
}
void main()
{int a=2,i;for(i=0;i<3;i++){printf("%d\n",f(a));} }

(1)靜態局部變量屬于靜態存儲類別,在靜態存儲區內分配存儲單元,在程序整個運行期間都不釋放。而我們的動態存儲是在棧里邊存儲,棧里面有一個特點就是你每當調用一個函數時,OK我給你生成一個棧,調用完這個函數后,OK,這個棧由系統自動回收(這就是輕輕的來輕輕的走不帶走一片內存,所以呢他不會占空間,而靜態的呢,他就永遠的呆在那里了直到你整個程序銷毀,所以靜態定義的多的話會比較占內存)。

(2)而動態變量(即動態局部變量)屬于動態存儲類別,占動態存儲區空間而不占靜態存儲區空間,所在函數調用結束后即釋放。

(3)對于靜態局部變量是在編譯時賦初值的,即只付初值一次,在程序運行時他已經有初值(比如上邊的c,在進行單步調試時,將斷點設置在for循環那里,第一次還未進入f函數時,c已經有值了是3了,在運行的時直接跳過c賦值了, 但是此時b還沒有值呢。當進入f函數后運行到b時,b才被賦值為0),以后每次調用函數時不再重新賦初值而是保留上次函數調用結束時的值。

而對自動變量賦初值時,不是在編譯時進行的,而是在函數調用時進行,每調用一次函數重新給一次初值,相當于執行一次賦值語句。

(4)如在定義局部變量時不賦初值的話,則對靜態變量來說,編譯時自動賦初值0(對數值型變量)或空字符(對字符型變量)。而對自動變量來說,如果不賦初值則他的值是一個不確定的值。一般是一個負的很大很大的數。這是由于每次函數調用結束后存儲單元已經釋放下次調用時又重新另外分配存儲單元,而所分配的單元中的值是不確定的。

(5)雖然靜態局部變量在調用結束后仍然存在,但其他函數是不能引用它的。(因為他是靜態的,他只歸他所有)

一般情況下,變量(包括靜態存儲方式和動態存儲方式)的值是存放在內存中的。 如果要執行都要經過這么個過程:

?

當程序中用到哪一個變量的值時,由控制器發出指令,將內存中該變量的值送到運算器中,經過運算器進行運算,如果需要存數,再從運算器將數據送到內存存放。

如果有一些變量使用頻繁,(例如一個函數中執行10000次循環,每次循環中都要引用某局部變量)那么這樣為存取變量的值要花費不少時間。為了提高執行效率,C語言允許將局部變量的值放在CPU中的寄存器,直接用時直接從寄存器取出參加運算,不必再到內存中去存取。由于寄存器的存取速度遠高于對內存的存取速度,因此這樣做可以提高執行效率。這種變量叫做寄存器變量,用關鍵字register做聲明。

#incluede<stdio.h>
int fac(int n)
{register int i;f=1;//把f和i都定義為寄存器,讓他存儲在寄存器,而不存儲在內存for(i=1;i<=n,i++){f*=i;}return (f)
}
void main()
{int i;for(i=1;i<=5;i++){printf("%d!=%d\n",i,fac(i))}
}
//但是不建議把所有的變量都變成寄存器,因為CPU的容量空間是有限的,所以他里邊的寄存器也是有限的

(6)extern聲明外部變量

外部變量即全局變量,他的作用域是從變量的定義開始,到本程序文件的末尾。在此作用域內全局變量可以為程序中各個函數所引用,編譯時將外部變量分配在靜態存儲區。有時需要用extern來聲明外部變量,以擴展外部變量的作用域。

#include<stdio.h>
int max(int x,int y)
{int z;z=x>y?x:y;return(z);
}
void main()//程序首先從main開始他extern了A,B(意思是告訴我們這個A和B的兩個變量是全局變量),我們如果去掉他就看了,因為他是在下邊定義的。如果是在上邊定義他就看到了,因為編譯器是從上往下讀的。而讀到此出還沒有讀到,所染A和B是全局變量因為他定義在各個函數之外。但是我們仍需要用extern聲明一下,告訴他他是全局變量,只是你現在還沒有看到他而已。這時候就能夠順利的調用他。(否則使用是在定義之前就不能編譯)
{extern a,b;//可以嘗試一下去掉extern關鍵字是什么后果print("%d\n",max(A,B))
}
int A=13,B=-6;

進階一下,在多個文件的程序中聲明外部變量

在此之前所講的所有的程序都是在一個程序中搞定的,就是在一個后綴名為.c的文件中搞定的但事實上我們遇到的一些程序,一些現成的程序他們都是由非常多的一些文件組成的,一個程序里你隨便打開一個程序它的內部源文件都是由非常多個文件組成的,每一個文件基本上都是實現了一個程序的部分功能,然后再把各個功能湊起來,所以我們現在需要學著把一個文件,把他拆成多個文件,都是來連接成這個程序的。

將一個程序拆成多個文件:

在一個文件中定義A。那么如果在另外一個文件中要使用就得extern A//表明A為一個已定義的外部變量。

用static聲明外部變量(static之前提到過聲明局部變量的化會使得這個局部變量不再是動態的存儲,他不再是因為每一個函數的返回而撤銷,它會一直的保存在內存里面,直到整個程序的結束,用static聲明一個局部變量的話也就是聲明一個內部變量或者局部變量的話就會使這個局部變量變成一個靜態變量。),那么用static聲明一個外部變量會怎么樣?

有時候在程序設計中,希望某些外部變量只限于被本文件引用,而不能被其他文件引用,這時就可以在定義外部變量時加一個static聲明(即增加了static不讓別的文件引用)。

關于變量的聲明和定義:

對變量而言,申明與定義的關系稍微復雜一些。在申明部分出現的變量有兩種情況:一種是需要建立內存儲空間的(如:int a;)另一種是不需要建立存儲空間的(如:extern a;)(像extern a就不需要建立內存空間,它只是告訴編譯器說已經有a這么一個定義的存在了。)那么前者叫做定義性聲明或稱為定義,后者叫做引用性聲明(而單單只是聲明不是定義,定義的話要建立存儲空間的)。

一般為了敘述方便,把建立存儲空間的聲明稱為定義,而把不需要建立存儲空間的聲明稱為聲明。顯然這里指的聲明是狹義的,即非定義性聲明。

PS:小結一下:

(1)從作用域(就是作用范圍)角度分,有局部變量和全局變量。他們采用的存儲類別如下:

局部變量(就是只能看到本函數)自動變量auto,即動態局部變量(離開函數,值就消失)
靜態局部變量static(離開函數,值仍保留)
寄存器變量(離開函數,值就消失)(它只是存的位置不同存在哪里,寄存器)
(形式參數可以定義為自動變量或寄存器變量,但是不能定義為靜態變量會報錯的)
全局變量(就是在最外層都看得到的)靜態外部變量(只限本文件引用)
外部變量
(即非靜態的外部變量,允許其他文件引用)

(2)從變量存在的時間(生存期)來區分,有動態存儲和靜態存儲兩種類型。靜態存儲是程序整個運行時間都存在(等到整個程序停下來之后整個程序結束之后他才會消失),而動態存儲則是調用函數時臨時分配單元(而動態存儲他是整個函數結束之后才會消失)。(因為他們存儲的范圍不同,也就是他們在內存中呆的位置不同,而使他們不同的存儲時間。像靜態存儲他是放在data段的,數據段的。而動態存儲他是放在棧段的,所以他會臨時消失)

動態存儲自動變量(本函數內有效)
寄存器變量(本函數內有效)
形式參數(本函數內有效)
靜態存儲靜態局部變量(函數內有效)
靜態外部變量(本文件內有效)
外部變量(其他文件可引用)

(3)從變量值存放位置來區分,可分為:

內存中靜態存儲區靜態局部變量
靜態外部變量(函數外部靜態變量)
外部變量(可為其他文件引用)
內存中動態存儲區域(也就是棧區)自動變量和形式參數
CPU中的寄存器寄存器變量

關于作用域和生存期,前者是從空間角度,后者是從時間角度。

(4)static對局部變量和全局變量的作用域不同。

對局部變量來說,他使變量由動態存儲存儲改變為靜態存儲。對于全局變量,它使變量局部化(只是局部于本文件),但仍為靜態存儲方式。從作用域角度看,凡有static聲明,其作用域都是局限的,或者是局限與本函數(靜態局部變量),或者局限于本文件內(靜態外部變量)

------內部函數和外部函數----

函數本質上是全局的,因為一個函數要被另外的函數調用,但是也可以指定函數不能被其他文件調用。

我們根據函數能否被其他源文件調用,將函數區分為內部函數和外部函數。

如果一個函數只能被本文件中其他函數所調用,它稱為內部函數。

在定義內部函數時,在函數名和函數類型的前面加static。即;

即static類型標識符   函數名(形參表)
如static int fun(int a,int b)

(1)在定義函數時,如果在函數首部的最左端加關鍵字extern,則表示此函數是外部函數,可供其他文件調用。如函數首部可以寫為extern int fun(int a,int b)

這樣,函數fun就可以為其他文件調用。C語言規定,如果在定義函數時省略extern,則隱含為外部函數。

總結

以上是生活随笔為你收集整理的C语言:随笔4的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。