国产女人18毛片水真多18精品, 一区二区三区中文字-亚洲精品女国产, 欧美熟妇老熟妇88888久久久久, 一级毛片免费观看亚洲欧美国产精品,大波霸美女视频,日韩欧美激情V影院,熟女人伦21p,亚洲精品女国产,国产 乱子伦 在线

C語言指針的傳遞

時間:2025-12-17 08:02:04 C語言 我要投稿

C語言指針的傳遞

  傳遞指針可以讓多個函數(shù)訪問指針所引用的對象,而不用把對象聲明為全局可訪問,要在某個函數(shù)中修改數(shù)據(jù),需要用指針傳遞數(shù)據(jù),當數(shù)據(jù)是需要修改的指針的時候,就要傳遞指針的指針,傳遞參數(shù)(包括指針)的時候,傳遞的是它們的值,也就是說,傳遞給函數(shù)的是參數(shù)值的一個副本,本文將討論C語言中指針傳遞給函數(shù)與從函數(shù)返回指針的內容。

  用指針傳遞數(shù)據(jù)

  用指針傳遞數(shù)據(jù)的一個主要原因是函數(shù)可以修改數(shù)據(jù)

  下面的代碼實現(xiàn)一個常見的交換函數(shù):

  #include

  void swap(int* a, int* b)

  {

  int tmp;

  tmp = *a;

  *a = *b;

  *b = tmp;

  }

  int main()

  {

  int m, n;

  m = 5;

  n = 10;

  printf("m=%d, n=%d ",m, n);

  swap(&m, &n);

  printf("m=%d, n=%d ",m, n);

  return 0;

  }

  如果不通過指針傳遞參數(shù),交換就不會發(fā)生,具體的原理參見任何一本C語言教材

  傳遞指向常量的指針

  傳遞指向常量的指針是C中常用的技術,效率很高,因為避免某種情況下復制大量內存,如果不希望數(shù)據(jù)被修改,就要傳遞指向常量的指針

  我們不能修改通過指向常量的指針傳進來的值:

  #include

  void passconstant(const int* num1, int*num2)

  {

  *num2 = *num1;

  }

  int main()

  {

  const int a = 100;

  int b = 5;

  printf("a=%d, b=%d ",a, b);

  passconstant(&a, &b);

  printf("a=%d, b=%d ",a, b);

  return 0;

  }

  下面的代碼會產生錯誤(第二個形參和實參的類型不匹配,試圖修改第一個參數(shù)所引用的常量):

  #include

  void passconstant(const int* num1, int* num2)

  {

  *num1 = 100;

  *num2 = 200;

  }

  int main()

  {

  const int limit = 100;

  passconstant(&limit, &limit);

  return 0;}

  C語言中堆和棧的區(qū)別

  預備知識—程序的內存分配

  一個由C編譯的程序占用的內存分為以下幾個部分:

  1、棧區(qū)(stack)— 由編譯器自動分配釋放 ,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結構中的棧。

  2、堆區(qū)(heap) — 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數(shù)據(jù)結構中的堆是兩回事,分配方式倒是類似于鏈表。

  3、全局區(qū)(靜態(tài)區(qū))(static),全局變量和靜態(tài)變量的存儲是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域, 未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域。程序結束后由系統(tǒng)釋放。

  4、文字常量區(qū) —常量字符串就是放在這里的, 程序結束后由系統(tǒng)釋放

  5、程序代碼區(qū)—存放函數(shù)體的二進制代碼。

  下面就說說C語言程序內存分配中的堆和棧,內存分配一般情況下程序存放在Rom或Flash中,運行時需要拷到內存中執(zhí)行,內存會分別存儲不同的信息,如下圖所示:

  內存中的棧區(qū)處于相對較高的地址以地址的增長方向為上的話,棧地址是向下增長的,棧中分配局部變量空間,堆區(qū)是向上增長的用于分配程序員申請的內存空間。另外還有靜態(tài)區(qū)是分配靜態(tài)變量,全局變量空間的;只讀區(qū)是分配常量和程序代碼空間的;以及其他一些分區(qū)。

  堆棧的區(qū)別,來看一個經典例子:

  #include

  #include

  int a = 0; /pic/p>

  char *p1; /pic/p>

  int main()

  {

  int b; /pic/p>

  char s[] = "abc"; /pic/p>

  char *p2; /pic/p>

  char *p3 = "123456"; /pic/p>

  static int c =0; /pic/p>

  p1 = (char*)malloc(10); /pic/p>

  p2 = (char*)malloc(10);

  return 0;

  }

  不知道你是否有點明白了,堆和棧的第一個區(qū)別就是申請方式不同:棧(英文名稱是stack)是系統(tǒng)自動分配空間的,例如我們定義一個 char a;系統(tǒng)會自動在棧上為其開辟

  空間。而堆(英文名稱是heap)則是程序員根據(jù)需要自己申請的空間,例如malloc(10);由于棧上的空間是自動分配自動回收的,所以棧上的數(shù)據(jù)的生存周期只是在函數(shù)的運行過程中,運行后就釋放掉,不可以再訪問。而堆上的數(shù)據(jù)只要程序員不釋放空間,就一直可以訪問到,不過缺點是一旦忘記釋放會造成內存泄露。還有其他的一些區(qū)別網上的總結的不錯這里轉述一下:

  1.申請后系統(tǒng)的響應

  棧:只要棧的剩余空間大于所申請空間,系統(tǒng)將為程序提供內存,否則將報異常提示棧溢出。

  堆:首先應該知道操作系統(tǒng)有一個記錄空閑內存地址的鏈表,當系統(tǒng)收到程序的申請時,會遍歷該鏈表,尋找第一個空間大于所申請空間的堆結點,然后將該結點從空閑結點鏈表中刪除,并將該結點的空間分配給程序,另外,對于大多數(shù)系統(tǒng),會在這塊內存空間中的首地址處記錄本次分配的大小,這樣,代碼中的 語句才能正確的釋放本內存空間。另外,由于找到的堆結點的大小不一定正好等于申請的大小,系統(tǒng)會自動的將多余的那部分重新放入空閑鏈表中,也就是說堆會在申請后還要做一些后續(xù)的工作這就會引出申請效率的問題。

  2.申請效率的比較

  棧:由系統(tǒng)自動分配,速度較快。但程序員是無法控制的。

  堆:是由new分配的內存,一般速度比較慢,而且容易產生內存碎片,不過用起來最方便。

  3.申請大小的限制

  棧:在Windows下,棧是向低地址擴展的數(shù)據(jù)結構,是一塊連續(xù)的內存的區(qū)域。這句話的意思是棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預先規(guī)定好的,在 WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數(shù)),如果申請的空間超過棧的剩余空間時,將提示overflow。因此,能從棧獲得的空間較小。

  堆:堆是向高地址擴展的數(shù)據(jù)結構,是不連續(xù)的內存區(qū)域。這是由于系統(tǒng)是用鏈表來存儲的空閑內存地址的,自然是不連續(xù)的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計算機系統(tǒng)中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。

  4.堆和棧中的存儲內容

  棧: 在函數(shù)調用時,第一個進棧的是主函數(shù)中函數(shù)調用后的下一條指令(函數(shù)調用語句的下一條可執(zhí)行語句)的地址,然后是函數(shù)的各個參數(shù),在大多數(shù)的C編譯器中,參數(shù)是由右往左入棧的,然后是函數(shù)中的局部變量。注意靜態(tài)變量是不入棧的。 當本次函數(shù)調用結束后,局部變量先出棧,然后是參數(shù),最后棧頂指針指向最開始存的地址,也就是主函數(shù)中的下一條指令,程序由該點繼續(xù)運行。

  堆:一般是在堆的頭部用一個字節(jié)存放堆的大小。堆中的具體內容有程序員安排。

  堆和棧的區(qū)別可以引用一位前輩的比喻來看出:

  使用棧就象我們去飯館里吃飯,只管點菜(發(fā)出申請)、付錢、和吃(使用),吃飽了就走,不必理會切菜、洗菜等準備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自由度小。使用堆就象是自己動手做喜歡吃的菜肴,比較麻煩,但是比較符合自己的口味,而且自由度大。

  局部變量指針

  如果不了解程序棧如何工作,就很容易犯返回指向局部數(shù)據(jù)指針的錯誤,看下面的例子:

  #include

  #include

  int* allocateArray(int size, int value)

  {

  int arr[size];

  for(int i = 0; i < size; i++) {

  arr[i] = value;

  }

  return arr;

  }

  int main()

  {

  int* vector = allocateArray(5, 45);

  for(int i = 0; i < 5; i++) {

  printf("%d ", vector[i]);

  }

  return 0;

  }

  一旦函數(shù)返回,返回的數(shù)組地址也就無效,因為函數(shù)的棧幀從棧中彈出了

  有一種方法是把arr變量聲明為static,這樣會把變量的作用域現(xiàn)在在函數(shù)內部,但是分配在棧幀的外面,避免其他函數(shù)覆寫變量值

  #include

  #include

  int* allocateArray(int size, int value)

  {

  static int arr[10];

  for(int i = 0; i < size; i++) {

  arr[i] = value;

  }

  return arr;

  }

  int main()

  {

  int* vector = allocateArray(5, 45);

  for(int i = 0; i < 5; i++) {

  printf("%d ", vector[i]);

  }

  return 0;

  }

  返回指針

  從函數(shù)返回對象經常使用以下兩種技術:

  使用malloc在函數(shù)內部分配內存并返回其地址,調用者負責釋放返回的內存

  傳遞一個對象給函數(shù),讓函數(shù)修改它,這樣分配和釋放對象的內存都是調用者的責任

  #include

  #include

  int* allocateArray(int size, int value)

  {

  int* arr = (int*)malloc(size * sizeof(int));

  for(int i = 0; i < size; i++) {

  arr[i] = value;

  }

  return arr;

  }

  int main()

  {

  int* vector = allocateArray(5, 45);

  for(int i = 0; i < 5; i++) {

  printf("%d ", vector[i]);

  }

  free(vector);

  return 0;

  }

  下面這個版本的allocateArray函數(shù)傳遞了一個數(shù)組指針、數(shù)組的長度和用來初始化數(shù)組元素的值,返回指針只是為了方便

  #include

  #include

  int* allocateArray(int *arr, int size, int value)

  {

  if(arr != NULL) {

  for(int i = 0; i < size; i++) {

  arr[i] = value;

  }

  }

  return arr;

  }

  int main()

  {

  int* vector = (int*)malloc(5 * sizeof(int));

  allocateArray(vector, 5, 45);

  for(int i = 0; i < 5; i++) {

  printf("%d ", vector[i]);

  }

  free(vector);

  return 0;

  }

  傳遞指針的指針

  將指針傳遞給函數(shù)的時候,傳遞的是值,如果希望修改原指針而不是指針的副本,就需要傳遞指針的指針

  #include

  #include

  void allocateArray(int **arr, int size, int value)

  {

  *arr = (int*)malloc(size * sizeof(int));

  if(arr != NULL) {

  for(int i = 0; i < size; i++) {

  *(*arr + i) = value;

  }

  }

  }

  int main()

  {

  int* vector = NULL;

  allocateArray(&vector, 5, 45);

  for(int i = 0; i < 5; i++) {

  printf("%d ", vector[i]);

  }

  free(vector);

  return 0;

  }

  二叉樹遞歸實現(xiàn)與二重指針

  二叉樹的諸多操作往往是通過遞歸調用來實現(xiàn)的,這就決定,不能只通過main函數(shù)實現(xiàn)全部過程,其中還需要調用main外定義的函數(shù)。也因此,對main調用外定義的函數(shù)的參數(shù)傳遞,就有了嚴格的要求。在網上查找很多關于二叉樹建立的程序,但直接拷貝在自己計算機上運行卻發(fā)現(xiàn)不少錯誤,無法編譯通過。以下有關代碼編譯通過,不涉及二叉樹的全部操作,著重通過C語言實現(xiàn)二叉樹的創(chuàng)建過程說明遞歸實現(xiàn)與二重指針的相關問題。

  1、二叉樹的定義

  二叉樹的定義結構通常為如下形式:

  typedef struct Node

  {

  char ch;

  struct Node *lchild,*rchild;

  }Node,*BTree;

  Node一般可用來定義二叉樹節(jié)點,而*BTree可用來定義指向二叉樹(根節(jié)點)的指針

  2、內存動態(tài)分配

  采用內存動態(tài)分配需要用到malloc函數(shù)。值得注意的是,該函數(shù)在成功開辟新的內存時,默認返回void*指針,因此需要強制轉換成Node*形式,其調用形式如(Node*)malloc(sizeof(Node))

  3、遞歸調用

  因為遞歸調用的需要,二叉樹的一些操作需要獨立作為一個函數(shù)。但是,這些函數(shù)是在main中調用,因此傳遞的參數(shù)和返回的值的處理是非常重要的。另外注意,對二叉樹的操作,首先就需要知道二叉樹的入口,即指向二叉樹的指針,也即指向二叉樹根節(jié)點的指針。因此,所傳遞的參數(shù),則為指向根節(jié)點的指針。又因為涉及分配內存的操作,必須傳遞二級指針,如下程序,CreateTree函數(shù)可以是由返回值,也可以不具有返回值(因為傳遞的是地址)。在main函數(shù)中作了測試,返回的值為二叉樹根節(jié)點的值。

  void CreateTree(Node** pTree)

  {

  char ch;

  scanf("%c",&ch);

  if(chr == '#') {

  (*pTree) = NULL;

  } else {

  if(!((*pTree) = (Node*)malloc(sizeof(Node)))) {

  exit(OVERFLOW);

  }

  (*pTree)->ch = chr;

  CreateTree(&((*pTree)->lchild));

  CreateTree(&((*pTree)->rchild));

  }

  }


【C語言指針的傳遞】相關文章:

C語言的指針12-21

C語言指針的總結11-24

C語言指針的概念02-25

C語言指針的用法11-15

對C語言指針的總結12-09

C語言指針教學02-10

什么是C語言中指針 C語言指針的基礎使用12-17

如何理解C語言指針12-18

C語言指針變量的運算09-30

  • 相關推薦