詳解C語言-二級指針三種內存模型

二級指針相對於一級指針,顯得更難,難在於指針和數組的混合,定義不同類型的二級指針,在使用的時候有着很大的區別

第一種內存模型char *arr[]

若有如下定義

char *arr[] = {"abc", "def", "ghi"};

這種模型爲二級指針的第一種內存模型,在理解的時候應該這樣理解:定義了一個指針數組(char * []),數組的每個元素都是一個地址。

其實做爲一個學習者,有一個學習的氛圍跟一個交流圈子特別重要這裏我推薦一個C語言C++交流羣1075673198,不管你是小白還是轉行人士歡迎入駐,大家一起交流成長。

在使用的時候,若要使用中間量操作元素,那麼此時中間量應該定義爲

char *tmp = NULL;

如果要打印這個數組,那麼可以使用以下函數

	int i = 0;
	if (pArray == NULL)
	{
		return -1;
	}
	for (i = 0; i < num; i++)
	{
		printf("%s \n", pArray[i]);
	}
	return 0;
}

第二種內存模型char arr[][]

若有如下定義

char arr[3][5] = {"abc", "def", "ghi"};

種模型爲二級指針的第二種內存模型,在理解的時候應該這樣理解:定義了一個二維數組,有3個(5個char)空間的存儲變量。

在使用的時候,若要使用中間量操作元素,那麼此時中間量應該定義爲

char tmp[5] = { 0 };

如果要打印這個數組,那麼可以使用以下函數

nt printAarray(char pArray[][5], int num) {
	int i = 0;
	if (pArray == NULL)
	{
		return -1;
	}
	for (i = 0; i < num; i++)
	{
		printf("%s \n", pArray[i]);
	}
	return 0;
}

第三種內存模型char **arr

若有如下定義

char **arr = (char *)malloc(100 * sizeof(char *));//char arr[400]
arr[0] = (char *)malloc(100 * sizeof(char));//char buf[100]
arr[1] = (char *)malloc(100 * sizeof(char));
arr[2] = (char *)malloc(100 * sizeof(char));
strcpy(arr[0], "abc");
strcpy(arr[1], "def");
strcpy(arr[2], "ghi");
···
for(int i = 0; i < 3; i++)
  if(arr[i] != NULL)
    free(arr[i]);
free(arr);

這種模型爲二級指針的第二種內存模型,在理解的時候應該這樣理解:定義了一個二級指針,二級指針就是指向指針的指針,其實就是開闢了100個指針空間,存放了100個地址。這種寫法是第一種的簡化寫法

其實做爲一個學習者,有一個學習的氛圍跟一個交流圈子特別重要這裏我推薦一個C語言C++交流羣1075673198,不管你是小白還是轉行人士歡迎入駐,大家一起交流成長。

在使用的時候,若要使用中間量操作元素,那麼此時中間量應該定義爲

char *tmp = NULL

如果要打印這個數組,那麼可以使用以下函數

{
	int i = 0;
	if (pArray == NULL)
	{
		return -1;
	}
	for (i = 0; i < num; i++)
	{
		printf("%s \n", pArray[i]);
	}
	return 0;
}

例子

把第一種內存模型的數據排序,運算結果放到第三種內存模型中

include "stdio.h"
#include "string.h"
#include "stdlib.h"

char **SortArrayAndGen3Mem(const char ** const myArray1, int num, char *str, int *myNum) {
	char **p = NULL;
		p= (char **)malloc(num*sizeof(char *));
	if (myArray1==NULL || str==NULL|| myNum==NULL)
	{
		printf("傳入參數錯誤\n");
		p = NULL;
		goto END;
	}
	*myNum = num;
	for (int i = 0; i < num;i++)
	{
		p[i] = NULL;
		p[i] = (char)malloc(50 * sizeof(char));
		memset(p[i], 0, sizeof(p[i]));
		if (p[i]==NULL)
		{
			printf("內存分配錯誤!\n");
			goto END;
		}
		strcpy(p[i], myArray1[i]);
	}
	char *tmp;
	for (int i = 0; i < num; i++)
	{
		for (int j = i + 1; j < num; j++)
		{
			if (strcmp(p[i],p[j])>0)
			{
				char *tmp = p[i];
				p[i] = p[j];
				p[j] = tmp;
			}
		}
	}
	for (int i = 0; i < num; i++)
	{
		printf("%s \n", myArray1[i]);
	}

END:
	return p;
}

//釋放內存函數

void main() {
	int i = 0;
	char **myArray3 = NULL;
	int num3 = 0;
	//第一種內存模型
	char *myArray[] = {"bbbbb", "aaaaa", "cccccc"};
	char *myp = "111111111111";

	myArray3 = SortArrayAndGen3Mem(myArray, 3, myp, &num3);

	for (i=0; i<num3; i++)
	{
		printf("%s \n", myArray3[i]);
	}

	system("pause");
}
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

char **SortArrayAndGet3Mem(const char* const myArray1,int num,char *str,int *myNum);
int getArray(char ***newp,int num) ;
int freeArray(char ***newpfree,int num);
int sortTArray(char *p, int num);

void main() {
	char **myArray3=NULL;
	int num3=0;
	char *myArray[]={"bbbb","aaa","cccc"};
	char *myp="111111111";
	myArray3=SortArrayAndGet3Mem(myArray,3,myp,&num3);
	system("pause");
}

char **SortArrayAndGet3Mem(const char** const myArray1,int num,char *str,int *myNum) {
	int ret=0;
	char **p=NULL;
	int i=0;
	char **p1=NULL;
	p1=(char **)myArray1;
	ret=getArray(&p,num +1);
	for (i=0;i<num;i++)
	{
		strcpy(p[i],p1[i]);
	}
	strcpy(p[i], str);
	ret=sortTArray(p,num +1);
	for (i=0;i<num +1;i++)
	{
		printf("%s\n",p[i]);
	}
	ret=freeArray(&p,num +1);
	*myNum = num +1;
	return p;
}

int getArray(char ***newp,int num) {
	int i=0;
	int ret=0;
	char **tmp = NULL;
	tmp = (char **)malloc(num*sizeof(char *));
	for (i=0;i<num;i++)
	{
		tmp[i]=(char*)malloc(sizeof(char)*100);
	}
	*newp = tmp; //
	return 0;
}

//
int freeArray(char ***newpfree,int num) {
	char **p=NULL;
	int i=0;
	int ret=0;
	p=*newpfree;
	for (i=0;i<num;i++)
	{
		free(p[i]);
	}
	free(p);
	*newpfree = NULL; //
	return ret;
}

//int sortTArray(char ***Arraystr, int num)
int sortTArray(char **Arraystr, int num) {
	int i , j = 0;
	for (i=0; i<num; i++)
	{
		for (j=i+1; j<num; j++)
		{
			if (strcmp((Arraystr)[i],(Arraystr)[j])>0)
			{
				char tmp[100];
				strcpy(tmp,(Arraystr)[i]);
				strcpy((Arraystr)[i],(Arraystr)[j]);
				strcpy((Arraystr)[j],tmp);
			}
		}
	}
	for (i=0;i<num;i++)
	{
		printf("%s\n",(Arraystr)[i]);
	}
	return 0;
}

時間:2020-06-09

javascript 內存模型實例詳解

本文實例講述了javascript 內存模型.分享給大家供大家參考,具體如下: 我對於 JavaScript 的內存模型一直都比較困惑,很想了解在操作變量的時候,JS 是如何工作的.如果你和我有同樣的困惑,希望這篇文章能給你一些啓發. 譯文,喜歡原文的可以直接拉到底部 當我們聲明變量.初始化變量.更改變量值的時候,到底會發生什麼?JavaScript 是如何實現這些基本的功能?最重要的是,我們如何才能理解這些基礎知識? 本文將覆蓋以下 4 個方面: JavaScript 原始數據類型的變量聲明和

iOS通過逆向理解Block的內存模型

前言 正常情況下,通過分析界面以及 class-dump 出來頭文件就能對某個功能的實現猜個八九不離十.但是 Block 這種特殊的類型在頭文件中是看不出它的聲明的,一些有 Block 回調的方法名 dump 出來是類似這樣的: - (void)FM_GetSubscribeList:(long long)arg1 pageSize:(long long)arg2 callBack:(CDUnknownBlockType)arg3; 因爲這種回調看不到它的方法簽名,我們無法知道這個 Block

Java8內存模型PermGen Metaspace實例解析

一.JVM 內存模型 根據 JVM 規範,JVM 內存共分爲虛擬機棧.堆.方法區.程序計數器.本地方法棧五個部分. 1.虛擬機棧:每個線程有一個私有的棧,隨着線程的創建而創建.棧裏面存着的是一種叫"棧幀"的東西,每個方法會創建一個棧幀,棧幀中存放了局部變量表(基本數據類型和對象引用).操作數棧.方法出口等信息.棧的大小可以固定也可以動態擴展.當棧調用深度大於JVM所允許的範圍,會拋出StackOverflowError的錯誤,不過這個深度範圍不是一個恆定的值,我們通過下面這段程序可以測

詳解C語言中的內存四區模型及結構體對內存的使用

內存四區 1.代碼區 代碼區code,程序被操作系統加載到內存的時候,所有的可執行代碼都加載到代碼區,也叫代碼段,這塊內存是不可以在運行期間修改的. 2.靜態區 所有的全局變量以及程序中的靜態變量都存儲到靜態區. 3.棧區 棧stack是一種先進後出的內存結構,所有的自動變量,函數的形參都是由編譯器自動放出棧中,當一個自動變量超出其作用域時,自動從棧中彈出.對於自動變量,什麼時候入棧,什麼時候出棧,是不需要程序控制的,由C語言編譯器.實現棧不會很大,一般都是以K爲單位的. 當棧空間以滿,但還往棧

詳解Java語言中一個字符佔幾個字節?

題主要區分清楚內碼(internal encoding)和外碼(external encoding)就好了. 內碼是程序內部使用的字符編碼,特別是某種語言實現其char或String類型在內存裏用的內部編碼: 外碼是程序與外部交互時外部使用的字符編碼.“外部"相對"內部"而言:不是char或String在內存裏用的內部編碼的地方都可以認爲是"外部”.例如,外部可以是序列化之後的char或String,或者外部的文件.命令行參數之類的. Java語

詳解易語言中的數據類型

各種數據存放在磁盤或內存中都有其不同的存放格式,因此就存在不同的數據類型.瞭解各種數據的特性,對編程開發來說是十分重要. 程序中經常會進行一些運算,易語言中的運算都要使用運算符進行識別處理,並通過運算表達式來完成運算操作.程序中對各數據之間的關係的描述也要通過運算符. 1.易語言的數據類型 一個程序內部應包括兩個方面的內容:1.數據的描述.2.操作步驟,即對程序動作的描述. 數據是程序操作的對象,操作的結果會改變數據的內容.打個比方:要做一道菜,做菜前先選擇烹飪的原材料(即對數據進行描述),然後

詳解Swift語言中的類與結構體

image

類 在 Swift 中類是建立靈活的構建塊.類似於常量,變量和函數,用戶可以定義的類的屬性和方法.Swift給我們提供了聲明類,而無需用戶創建接口和實現文件的功能.Swift 允許我們創建類作爲單個文件和外部接口,將默認在類一次初始化來創建. 使用類的好處: 繼承獲得一個類的屬性到其他類 類型轉換使用戶能夠在運行時檢查類的類型 初始化器需要處理釋放內存資源 引用計數允許類實例有一個以上的參考 類和結構的共同特徵: 屬性被定義爲存儲值 下標被定義爲提供訪問值 方法被初始化來改善功能 初始狀態是由初

詳解C語言中的函數、數組與指針

1.函數:當程序很小的時候,我們可以使用一個main函數就能搞定,但當程序變大的時候,就超出了人的大腦承受範圍,邏輯不清了,這時候就需要把一個大程序分成許多小的模塊來組織,於是就出現了函數概念:   函數是C語言代碼的基本組成部分,它是一個小的模塊,整個程序由很多個功能獨立的模塊(函數)組成.這就是程序設計的基本分化方法: (1) 寫一個函數的關鍵: 函數定義:函數的定義是這個函數的實現,函數定義中包含了函數體,函數體中的代碼段決定了這個函數的功能: 函數聲明:函數聲明也稱函數原型聲明,函數的原

詳解C語言中結構體的自引用和相互引用

結構體的自引用(self reference),就是在結構體內部,包含指向自身類型結構體的指針. 結構體的相互引用(mutual reference),就是說在多個結構體中,都包含指向其他結構體的指針. 1. 自引用 結構體 1.1 不使用typedef時 錯誤的方式: struct tag_1{ struct tag_1 A; /* 結構體 */ int value; }; 這種聲明是錯誤的,因爲這種聲明實際上是一個無限循環,成員b是一個結構體,b的內部還會有成員是結構體,依次下去,無線循環.

詳解c語言中的 strcpy和strncpy字符串函數使用

strcpy 和strcnpy函數–字符串複製函數. 1.strcpy函數 函數原型:char *strcpy(char *dst,char const *src)            必須保證dst字符的空間足以保存src字符,否則多餘的字符仍然被複制,覆蓋原先存儲在數組後面的內存空間的數值,strcpy無法判斷這個問題因爲他無法判斷字符數組的長度. #include <stdio.h> #include<string.h> int main() { char message

詳解Go 語言中的比較操作符

這篇文章專注於 6 個操作符,==,!=,<,<=,> 和 >=.我們將深入探討它們的語法和用法的細微差別.對很多人來說,這聽起來不像是吸引人的事,或者他們可能已經從其他編程語言獲得了糟糕的經驗.然而,在 Go 中它們定義的很好並簡潔.下面討論的主題,如可比性將出現在其他場合,如 maps.爲了使用上述操作符,至少有一個操作數需要可賦值給第二個操作數: package main import “fmt” type T struct { name string }

詳解C語言中的指針與數組的定義與使用

指針的特點 他就是內存中的一個地址 指針本身運算 指針所指向的內容是可以操作的 操作系統是如何管理內存的 棧空間 4M~8m的大小 當進入函數的時候會進行壓棧數據 堆空間 4g的大小 1g是操作系統 全局變量 內存映射 可以對內存的內容修改修改硬盤的內容 一般在數據庫中經常使用 內存的分配與釋放 c語言分配內存的方法 // malloc(需要分配的大小): 這裏的分配的大小需要對齊的2的指數 void *mem = malloc(size); 釋放內存 // 一般分配的內容都是在堆空間中的 //

詳解C語言中的符號常量、變量與算術表達式

C語言中的符號常量 在結束討論溫度轉換程序前,我們再來看一下符號常量.在程序中使用 300.20 等類似的"幻數"並不是一個好習慣,它們幾乎無法向以後閱讀該程序的人提供什麼信息,而且使程序的修改變得更加困難.處理這種幻數的一種方法是賦予它們有意義的名字.#define 指令可以把符號名(或稱爲符號常量)定義爲一個特定的字符串: #define 名字 替換文本 在該定義之後,程序中出現的所有在 #define 中定義的名字(既沒有用引號引起來,也不是其它名字的一部分)都將用相應的替換文本.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章