程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 詳解C說話中的內存四區模子及構造體對內存的應用

詳解C說話中的內存四區模子及構造體對內存的應用

編輯:關於C++

詳解C說話中的內存四區模子及構造體對內存的應用。本站提示廣大學習愛好者:(詳解C說話中的內存四區模子及構造體對內存的應用)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解C說話中的內存四區模子及構造體對內存的應用正文


內存四區
1、代碼區
代碼區code,法式被操作體系加載到內存的時刻,一切的可履行代碼都加載到代碼區,也叫代碼段,這塊內存是弗成以在運轉時代修正的。
2、靜態區
一切的全局變量和法式中的靜態變量都存儲到靜態區。
3、棧區
棧stack是一種先輩後出的內存構造,一切的主動變量,函數的形參都是由編譯器主動放出棧中,當一個主動變量超越其感化域時,主動從棧中彈出。關於主動變量,甚麼時刻入棧,甚麼時刻出棧,是不須要法式掌握的,由C說話編譯器。完成棧不會很年夜,普通都是以K為單元的。
當棧空間以滿,但還往棧內存壓變量,這個就叫棧。溢出關於一個32位操作體系,最年夜治理治理4G內存,個中1G是給操作體系本身用的,剩下的3G都是給用戶法式,一個用戶法式實際上可使用3G的內存空間。
留意:C說話中函數參數入棧的次序是從右往左。
4、堆區
堆heap和棧一樣,也是一種在法式運轉進程中可以隨時修正的內存區域,但沒有棧那樣先輩後出的次序。堆是一個年夜容器,它的容量要遠弘遠於棧,然則在C說話中,堆內存空間的請求和釋放須要手動經由過程代碼來完成。
代碼示例:

#include <stdio.h> 
 
int c = 0; // 靜態區 
 
void test(int a, int b) // 形參a,b都在棧區 
{ 
  printf("%d, %d\n", &a, &b); 
} 
 
int *geta() // 函數的前往值是一個指針 
{ 
  int a = 100; // 棧區 
  return &a; 
} // int a的感化域就是這個{} 
 
int main() 
{ 
  int *p = geta(); // 這裡獲得一個暫時棧變量的地址,這個地址在函數geta挪用完成以後曾經有效了 
  *p = 100; 
  printf("%d\n", *p); 
  static int d = 0; // 靜態區 
  int a = 0; // 棧區 
  int b = 0; 
 
  printf("%d, %d, %d, %d, %d\n", &a, &b, &c, &d, main); 
  test(a, b); 
  return 0; 
} 
 
/* 
輸入成果 
100 
2619740, 2619728, 9404720, 9404724, 9376059 
2619512, 2619516 
*/ 

堆應用留意事項:

#include <stdio.h> 
#include <stdlib.h> 
 
int *geta() // 毛病,不克不及將一個棧變量的地址經由過程函數的前往值前往 
{ 
  int a = 0; 
  return &a; 
} 
 
int *geta1() // 可以經由過程函數的前往值前往一個堆地址,但記得,必定要free 
{ 
  int *p = (int *)malloc(sizeof(int)); // 請求了一個堆空間 
  return p; 
} 
 
int *geta2() // 正當的,然則記住這裡不克不及用free 
{ 
  static int a = 0; // 變量在靜態區,法式運轉進程中一向存在 
  return &a; 
} 
 
void getHeap(int *p) 
{ 
  printf("p = %p\n", &p); 
  p = (int *)malloc(sizeof(int) * 10); 
} // getHeap履行完以後,p就消逝了,招致他指向的詳細堆空間的地址編號也隨之消逝了 
// 這裡產生了內存洩露 
 
void getHeap1(int **p) 
{ 
  *p = (int *)malloc(sizeof(int) * 10); 
} // 這裡的操作就是准確的 
 
int main() 
{ 
  int *p = NULL; 
  printf("p = %p\n", &p); 
  getHeap(p); // 實參沒有任何轉變 
  getHeap1(&p); // 獲得了堆內存的地址 
  printf("p = %d\n", p); 
 
  p[0] = 1; 
  p[1] = 2; 
  printf("p[0] = %d, p[1] = %d\n", p[0], p[1]); 
  free(p); 
 
  return 0; 
} 


構造體內存對齊形式

構造體內存對齊形式各類情形詳解

#include <stdio.h> 
 
struct A 
{ 
  int a; // 此時構造體占用4個字節 
  char b; // 此時構造體占用8個字節 
  char c; // 照樣8個字節 
  char d; // 照樣8個字節 
  char e; // 照樣8個字節 
  char f; // 如今是12個字節  
}; 
 
struct B 
{ 
  char a; // 1個字節 
  char b; // 2個字節 
  char c; // 3個字節 
}; 
 
struct c 
{ 
  char name[10]; // 10個字節 
  char a; // 11個字節 
  // 關於char型數組來講,會把數組每一個元素看成一個char類型 
}; 
 
struct d 
{ 
  int name[10]; // 40個字節 
  char a; // 44個字節 
  char b; // 44個字節 
}; 
 
struct e 
{ 
  char a; // 1個字節 
  int b; // 8個字節 
  char c; // 12個字節 
  // 這類寫法內存的消費比擬A就會變年夜 
}; 
 
struct f 
{ 
  char a; // 1 
  short b; // 4留意這裡short占用的是剩下三個字節中的後兩個 
  // 內存對齊老是以2的倍數對齊 
  char c; // 所以此時是6 
  int d; // 12 
  short e; // 16 
  char f; // 16 
}; 


構造體變相完成數組賦值

struct name 
{ 
  char array[10]; 
}; 
 
int main() 
{ 
  char name1[10] = "name1"; 
  char name2[20] = "name2"; 
  name1 = name2; // 這裡是失足的,不克不及在數組之間停止賦值 
  struct name a1 = { "hello" }; 
  struct name a2 = { 0 }; 
  a2 = a1; // 這裡經由過程構造體可以賦值的特征變相完成了數組的賦值 
  return 0; 
} 


構造體內存洩露

#include <stdio.h> 
#include <stdlib.h> 
 
union A 
{ 
  char a; 
  char *b; // 結合體的指針成員要特殊留意 
}; 
 
int main() 
{ 
  A a; 
  a.b = (char *)malloc(10); // b指向了一個堆的地址 
  // 假如結合體中有指針成員,那末必定要應用完這個指針,而且free指針以後能力應用其他成員 
  a.a = 10; // b的值同樣成了10了 
  free(b); // 此時釋放b是毛病的,由於在下面一行對a停止賦值時,曾經將b的值更改了,這裡形成了內存洩露 
  return 0; 
} 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved