C語言進階--數據的存儲

1.數據類型介紹

內置類型

char  //字符數據類型  1字節
short  //短整型      2字節
int  //整型          4字節
long  //長整型       4/8字節
long long  //更長的整型  8字節   (C99中引入的)
float  //單精度浮點數    4字節
double  //雙精度浮點數   8字節sizeof(long) >= sizeof(int)
4(32位平臺)/8(64位平臺)  >=  4   字節

類型的意義

  • 使用這個類型開辟內存空間的大小(大小決定使用范圍)
  • 如何看待內存空間的視角

1.1類型的基本歸類

整型家族

char    (字符的本質是ASCII碼值,屬于整型,所以劃分到整型家族)  (char 類型 到底是signed char 還是unsigned char ,在C語言標準中是未定義的,取決于編譯器的實現) —— char 比較特殊unsigned charsigned charshortunsigned short [int]signed short [int]int     (int a; ————> 這里的int類型默認指的是signed int) unsigned intsigned intlongunsigned long [int]signed long [int]long longunsigned long long [int] signed long long [int]

生活中有些數據是沒有負數的,比如身高,體重,長度等。 ——> unsigned

但有些數據是有負數的,比如溫度。——> signed

浮點型家族

float
double

只要是表示小數就可以使用浮點型。

float的精度低,存儲的數值范圍較小;double的精度高,存儲的數值范圍更大。

構造類型(自定義類型:我們可以自己創建出新的類型)

數組類型
結構體類型 struct
枚舉類型 enum
聯合類型 union    
//數組類型
int arr1[5]; //數組類型:int [5]
int arr2[8]; //數組類型:int [8]
char arr3[5]; //數組類型:char [5]

指針類型

int* pi;
char* pc;
float* pf;
void* pv;

空類型

void 表示空類型(無類型)
通常應用于函數的返回類型、函數的參數、指針類型    
void test(void) //第一個void 表示函數沒有返回值;第二個void 表示函數不需要傳任何參數
{}

2.整型在內存中的存儲

一個變量的創建是要在內存中開辟空間的。空間的大小是根據不同的類型而決定的。

//數值有不同的表示形式,2進制,8進制,10進制,16進制
//eg:21
//0b10101 —— 025 —— 21 —— 0x15

2.1原碼、反碼、補碼

整數的2進制表示也有3種表示形式:原碼、反碼、補碼。

1.正的整數,原碼、反碼、補碼相同。

2.負的整數,原碼、反碼、補碼是需要計算的。

原碼(直接通過正負的形式寫出的二進制序列)

反碼(原碼的符號位不變,其它位按位取反)

補碼(反碼+1)

int main()
{int a = 20;//00000000 00000000 00000000 00010100 - 原碼(二進制)//0x00 00 00 14 - 原碼、反碼、補碼(十六進制)//00000000 00000000 00000000 00010100 - 反碼(二進制)//00000000 00000000 00000000 00010100 - 補碼(二進制)int b = -10;//10000000 00000000 00000000 00001010 - 原碼(二進制)//0x80 00 00 0a - 原碼(十六進制)//11111111 11111111 11111111 11110101 - 反碼(二進制)//0xff ff ff f5 - 反碼(十六進制)//11111111 11111111 11111111 11110110 - 補碼(二進制)   //0xff ff ff f6 - 補碼(十六進制)return 0;
}

在這里插入圖片描述
整數在內存中存放的是補碼的二進制序列。

為什么呢?

在計算機系統中,數值一律用補碼來表示和存儲。原因在于,使用補碼,可以將符號位和數值域統一處理;同時,加法和減法也可以統一處理(CPU只有加法器)。此外,補碼與原碼相互轉換,其運算過程是相同的,不需要額外的硬件電路。

2.2大小端介紹

在這里插入圖片描述
大端【字節序】存儲:把一個數據的高位字節序的內容放在低地址處,把低位字節序的內容放在高地址處。

小端【字節序】存儲:把一個數據的高位字節序的內容放在高地址處,把低位字節序的內容放在低地址處。

我們常用的X86結構是小端模式,而KEIL C51為大端模式。很多的ARM,DSP都為小端模式。有些ARM處理器還可以由硬件來選擇大端模式還是小端模式。

//判斷大小端
#include <stdio.h>int main()
{int a = 1;if (*(char*)&a == 1){printf("小端\n");}else{printf("大端\n");}return 0;
}
//判斷大小端(封裝成函數)
#include <stdio.h>
int check_sys()
{int a = 1;if (*(char*)&a == 1){return 1;}else{return 0;}
}
int main()
{int ret = check_sys();if (ret == 1)printf("小端\n");elseprintf("大端\n");return 0;
}
//判斷大小端(封裝成函數,簡潔版)
#include <stdio.h>
int check_sys()
{int a = 1;return *(char*)&a;
}
int main()
{int ret = check_sys();if (ret == 1)printf("小端\n");elseprintf("大端\n");return 0;
}

3.浮點型在內存中的存儲

常見的浮點數:

3.14159

1E10(1.0*e的10次方,科學計數法)

浮點數家族:float、double、long double(C99中引入)類型。

浮點數表示的范圍:float.h中定義。

整數表示的范圍:limits.h中定義。

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

3.1浮點數存儲序列

根據國際標準IEEE(電氣和電子工程協會)754,任意一個二進制浮點數V可以表示成下面的形式:

(-1)^S * M * 2^E

  • (-1)^S【-1的S次方】表示符號位。當S=0,V為正數;當S=1,V為負數。
  • M表示有效數字。大于等于1,小于2.
  • 2^E【2的E次方】表示指數位。

IEEE 754規定:

對于32位的浮點數,最高的1位是符號位S,接著的8位是指數E,剩下的32位是有效數字M。

在這里插入圖片描述
對于64位的浮點數,最高的1位是符號位S,接著的11位是指數E,剩下的52位是有效數字M。

在這里插入圖片描述
IEEE 754對有效數字M和指數E,還有一些特別的規定:

前面說過,1<=M<2,也就是說,M可以寫成1.xxxx的形式,其中xxxx表示小數部分。

IEEE 754規定,在計算機內部保存M時,默認這個數的第一位總是1,因此可以被舍去,只保存后面的xxxx部分。比如保存1.01時,只保存01,等到讀取的時候,再把第一位的1加上去。這樣做的目的:節省1位有效數字。

至于指數E,情況比較復雜。

首先,E為一個無符號整數(unsigned int),這意味著,如果E為8位,它的取值范圍是0-255;如果E為11位,它的取值范圍是0-2047。但是,我們知道,科學計數法中的E是可以出現負數的。所以IEEE 754規定,存入內存時E的真實值必須再加上一個中間數。對于8位的E,這個中間數是127;對于11位的E,這個中間數是1023。

int main()
{float f = 5.5f;//101.1 - 二進制//1.011*2^2 - 科學計數法//S=0,M=1.011,E=2(存儲時+中間值127=129)//0 10000001 011(后面不足23bit直接補0)00000000000000000000//01000000101100000000000000000000//0100 0000 1011 0000 0000 0000 0000 0000(寫出16進制)//0x40 b0 00 00return 0;
}

在這里插入圖片描述
然后,指數E從內存這種取出還可以分成三種情況:

E不全為0或不全為1

這時,浮點數就采用下面的規則表示:即指數E的計算值減去127(或1023),得到真實值,再將有效數字M前加上第一位的1。

比如:

0 10000001 01100000000000000000000
(-1)^0 * 1.01100000000000000000000 * 2^2129-127=2

E全為0

這時,浮點數的指數E等于1-127(或者1-1023),即位真實值。有效數字M也不再加上第一位的1,而是還原為0.xxxx的小數。這樣做是為了表示正負0,以及接近于0的很小的數字。

E全為1

這時,如果有效數字M全為0,表示正負無窮大(正負取決于符號位S)。

作業1:輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得數組中所有的奇數位于數組的前半部分,所有偶數位于數組的后半部分。

//輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得數組中所有的奇數位于數組的前半部分,所有偶數位于數組的后半部分。#include <stdio.h>void move_odd_even(int arr[], int sz)
{int left = 0;int right = sz - 1;while (left < right){//從左向右找一個偶數,遇到奇數停下來while ((left < right)&& (arr[left] % 2 == 1)) //可能存在越界,加上條件(left < right){left++;}//從右向左找一個奇數,遇到偶數停下來while ((left < right)&& (arr[right] % 2 == 0)){right--;}//交換奇數和偶數if (left < right){int tmp = arr[left];arr[left] = arr[right];arr[right] = tmp;left++;right--;}}
}
int main()
{int arr[10] = {0};//輸入int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);for (i = 0; i < sz; i++){//scanf("%d", &arr[i]); //等價于下面代碼scanf("%d", arr+i);}//調整move_odd_even(arr, sz);//輸出for (i = 0; i < sz; i++){printf("%d ", arr[i]); }return 0;
}

作業2:有序序列合并

#include <stdio.h>
int main()
{int n = 0;int m = 0;scanf("%d %d", &n, &m);int arr1[n]; //C99支持的變長數組int arr2[m];//輸入n個整數int i = 0;for (i = 0; i < n; i++){scanf("%d", &arr1[i]);}//輸入m個整數for (i = 0; i < m; i++){scanf("%d", &arr2[i]);}//合并打印int j = 0; //n數組下標int k = 0; //m數組下標while (j<n && k<m){if (arr1[j] < arr2[k]){printf("%d ", arr1[j]);j++;}else{printf("%d ", arr2[k]);k++;}}if (j<n){for (; j < n; j++){printf("%d ", arr1[j]);}}else //k<m{for (; k < m; k++){printf("%d ", arr2[k]);}}return 0;
}
//如果要存儲在一個新數組里面
#include <stdio.h>
int main()
{int n = 0;int m = 0;scanf("%d %d", &n, &m);int arr1[n]; //C99支持的變長數組int arr2[m];int arr3[m+n];//輸入n個整數int i = 0;for (i = 0; i < n; i++){scanf("%d", &arr1[i]);}//輸入m個整數for (i = 0; i < m; i++){scanf("%d", &arr2[i]);}//合并打印int j = 0; //arr1數組下標int k = 0; //arr2數組下標int r = 0; //arr3數組下標while (j<n && k<m){if (arr1[j] < arr2[k]){arr3[r++] = arr1[j];//printf("%d ", arr1[j]);j++;}else{arr3[r++] = arr2[k];//printf("%d ", arr2[k]);k++;}}if (j<n){for (; j < n; j++){arr3[r++] = arr1[j];//printf("%d ", arr1[j]);}}else //k<m{for (; k < m; k++){arr3[r] = arr2[k];//printf("%d ", arr2[k]);}}//打印for (i = 0; i < m+n; i++){printf("%d ", arr3[i]);}return 0;
}

總結

今天就暫且更新至此吧,期待下周再會。如有錯誤還請不吝賜教。希望對您學習有所幫助,翻頁前留下你的支持,以防下次失蹤了嗷。

作者更新不易,免費關注別手軟。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/82615.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/82615.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/82615.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++學習細節回顧(匯總三)

一.多態概念 同樣是動物叫的?個?為(函數)&#xff0c;傳貓對象過去&#xff0c;就是”(>ω<)喵“&#xff0c;傳狗對象過去&#xff0c;就是"汪汪"。 1.根據對象不同類型&#xff0c;調用不同函數&#xff0c;這就叫做運行時多態(動態多態) 2.編譯時多態(靜態…

SpringAI+MCPServer+MCPClient快速入門

SpringAI MCPServer MCPClient 快速入門編寫大綱 源代碼地址&#xff1a;https://download.csdn.net/download/user_admin_god/90926893 1. 介紹 本文通過使用免費的智普AI的glm-4-flash模型&#xff0c;設計并實現了一個智能問答系統。在該系統中&#xff0c;我們編寫了一…

Linux `vi/vim` 編輯器深度解析與高階應用指南

Linux `vi/vim` 編輯器深度解析與高階應用指南 一、核心功能解析1. 模式系統2. 與主流編輯器對比二、核心操作體系1. 高效導航命令2. 文本操作矩陣三、高階配置體系1. .vimrc 配置示例2. 插件管理系統四、企業級開發實踐1. 代碼編輯技巧2. 宏錄制與批量處理五、可視化與多窗口1…

Java五種方法批量處理List元素全解

Java:如何優雅批量處理List中的每個元素 一、場景分析&#xff1a;為什么需要批量處理List&#xff1f;二、核心方法&#xff1a;五種實現方式對比2.1 普通for循環&#xff08;最直接的方式&#xff09;代碼示例&#xff1a;優缺點&#xff1a; 2.2 Java 8 replaceAll&#xff…

【Elasticsearch】`_refresh`和`_flush`的區別

在Elasticsearch中&#xff0c;_refresh和_flush操作雖然看似都與“刷新”有關&#xff0c;但它們的功能和作用范圍有顯著區別&#xff1a; _refresh操作 - 目的&#xff1a;使索引操作&#xff08;如新增、更新、刪除文檔&#xff09;后的更改能夠立即被搜索到。 - 工作原理…

Java核心數據類型:String深度解析(JDK 8+)

&#x1f525;「炎碼工坊」技術彈藥已裝填&#xff01; 點擊關注 → 解鎖工業級干貨【工具實測|項目避坑|源碼燃燒指南】 問題驅動&#xff1a;從用戶注冊場景說起 場景描述&#xff1a;開發一個用戶注冊功能時&#xff0c;需要處理用戶名的校驗、格式化和存儲。你可能會遇到…

人員睡崗檢測算法AI智能分析網關V4打造工業/安防/交通等多場景應用方案

一、引言? 在工業生產、安防監控等多領域&#xff0c;眾多崗位需員工長時間值守&#xff0c;如流水線工人、監控值班員等。但高強度工作易引發睡崗問題&#xff0c;導致生產效率下降&#xff0c;甚至造成安全事故與財產損失。傳統人工巡檢響應慢、成本高&#xff0c;難以滿足…

自動生成提示技術突破:AUTOPROMPT重塑語言模型應用

AUTOPROMPT 預訓練語言模型的顯著成功促使人們研究這些模型在預訓練期間學習了哪些類型的知識。將任務重新表述為填空題(例如,完形填空測試)是衡量此類知識的自然方法 但是,它的使用受到編寫合適提示所需的手動工作和猜測的限制。為了解決這個問題,我們開發了 AUTOPROMP…

6個月Python學習計劃 Day 7 - 復盤 + 測試日

第一周 Day 1 - Python 基礎入門 & 開發環境搭建 Day 2 - 條件判斷、用戶輸入、格式化輸出 Day 3 - 循環語句 range 函數 Day 4 - 列表 & 元組基礎 Day 5 - 字典&#xff08;dict&#xff09;與集合&#xff08;set&#xff09; Day 6 - 綜合實戰&#xff1a;學生信息…

Pycharm and Flask 的學習心得(9)

request對象&#xff1a; 1. request包含前端發送過來的所有請求數據 將from表單里的內容CV到request里面&#xff0c;可以添加if語句來做判斷出請求類型后的操作 在網頁上的表單上input的數據&#xff0c;后端如何獲取呢&#xff1f; request對象獲取前端發送來的數據 // …

設計模式-依賴倒轉原則

依賴倒轉原則 依賴倒轉原則 (Dependency Inversion Principle, DIP) 是面向對象設計中 SOLID 原則的第五個原則。 它包含兩條核心思想&#xff1a; 高層模塊不應該依賴于低層模塊。兩者都應該依賴于抽象。 高層模塊 (High-level modules): 通常包含復雜的業務邏輯和策略&…

AI賦能引爆短劇全球化風潮,騰訊云媒體處理助力短劇平臺出海吸金

2023年&#xff0c;中國短劇市場以全平臺8000萬日投放、近500億規模的爆發式增長震驚行業。緊湊的內容、爽快的劇情令國內觀眾迅速愛上了幾分鐘一集的微短劇。然而在平臺內卷、監管收緊、巨頭入場等因素的沖擊下&#xff0c;不到兩年時間&#xff0c;這條賽道就已陷入紅海。但與…

開源第三方庫發展現狀

摘要&#xff1a;當前&#xff0c;開源第三方庫生態正呈現爆發式增長趨勢。GitHub 目前已托管超過 4.2 億個代碼倉庫&#xff0c;遠超早期統計的 1 億規模&#xff0c;顯示出開發者社區的活躍度持續攀升。同時&#xff0c;37 個主流包管理器所維護的開源組件數量可能已達到數千…

服務器開機自啟動服務

前言&#xff1a; 將服務器中腳本開啟自啟動執行 步驟&#xff1a; 1.創建一個 systemd 服務文件: /etc/systemd/system/ 目錄下創建一個新的服務文件。例如&#xff0c;命名為 myapp.service&#xff1a; sudo nano /etc/systemd/system/myapp.service2.編寫 [Unit] Descri…

采用Bright Data+n8n+AI打造自動化新聞助手:每天5分鐘實現內容日更

一、引言 在信息爆炸的時代&#xff0c;作為科技領域的內容創作者&#xff0c;我每天都要花費2-3小時手動收集行業新聞、撰寫摘要并發布到各個社群。直到我發現Bright Datan8nAI這套"黃金組合"&#xff0c;才真正實現了從"人工搬運"到"智能自動化&qu…

ROS云課三分鐘-3D性能測試supertuxkart和游戲推薦等-國際象棋

ROS云課三分鐘-破壁篇GCompris-一小部分支持Edu應用列表-2025-CSDN博客 很多時候&#xff0c;有一種思維定勢&#xff0c;將人鎖住&#xff0c;人口就是囚。 口人囚~口加人等于囚-CSDN博客 如果突破&#xff0c;跳出問題&#xff0c;再看問題。 這門課程&#xff0c;或者這個平…

學習率及相關優化參數詳解:驅動模型高效訓練

一、引言 在模型微調的核心參數體系中&#xff0c;優化相關參數是決定訓練效率與模型性能的關鍵變量。它們如同精密機械的齒輪&#xff0c;彼此聯動、相互影響&#xff0c;共同調控著模型在參數空間中的搜索路徑。本文將圍繞學習率、訓練輪數、批處理大小、梯度累積和學習率調…

golang 柯里化(Currying)

使用場景&#xff1a;參數在語義上屬于不同組&#xff0c;Go 語法無法在單次調用中聲明多組可變參數&#xff0c;通過柯里化可以實現分步接收參數。 有的參數是在不同時間段產生&#xff0c;使用Currying可以讓函數記住&#xff08;緩存&#xff09;參數&#xff0c;避免應用代…

電腦革命家測試版:硬件檢測,6MB 輕量無廣告 清理垃圾 + 禁用系統更新

各位電腦小白和大神們&#xff0c;我跟你們說啊&#xff01;有個超牛的東西叫電腦革命家測試版&#xff0c;這是吾愛破解論壇的開發者搞出來的免費無廣告系統工具集合&#xff0c;主打硬件檢測和系統優化&#xff0c;就像是魯大師這些軟件的平替。下面我給你們嘮嘮它的核心功能…

R 語言科研繪圖第 52 期 --- 網絡圖-分組

在發表科研論文的過程中&#xff0c;科研繪圖是必不可少的&#xff0c;一張好看的圖形會是文章很大的加分項。 為了便于使用&#xff0c;本系列文章介紹的所有繪圖都已收錄到了 sciRplot 項目中&#xff0c;獲取方式&#xff1a; R 語言科研繪圖模板 --- sciRplothttps://mp.…