主頁 > 軟體設計 > 【C語言從青銅到王者】第零篇·與C語言來個約會

【C語言從青銅到王者】第零篇·與C語言來個約會

2021-04-08 11:56:24 軟體設計

系列介紹
本系列博客是博主自己的C語言學習筆記,分享出來即是為了整理學過的知識也希望幫助每一位零基礎小白上手C語言,系列更新速度即為博主學習速度,如有錯誤疏漏,請務必及時指出!


本篇前言
如果說編程是一場MOBA游戲,程式員是召喚師,那編程語言就是代替我們“參戰”的英雄,C語言就是這樣一個位于T0級別的熱門英雄,常年位居TIOBE前三甲,是編程界當之無愧的“C位”,這篇文章,讓我們先來初步認識一下它的每一個“技能”到底是什么,在今后的文章里再對這些技能的使用技巧做進一步的講解,


目錄

  • 被動技能
    • 1.注釋
        • 注釋的意思
        • 注釋的作用
        • 注釋的寫法
    • 2.C語言程式基本框架
    • 3.資料型別
        • 常見的資料型別
        • 各種資料型別的大小
        • 資料型別的作用
    • 4.變數與常量
        • 什么是變數和常量
        • 定義變數的方法
        • 變數的分類
        • 變數的作用域和生命周期
        • 常量的分類
    • 5.字符、字串、轉義字符
        • 字符
        • 字串
        • 轉義字符
        • 字串的結束標志——字符終止符\0
    • 6.運算子
        • 算數運算子
        • 移位運算子
        • 位運算子
        • 賦值運算子與復合賦值符
        • 單目運算子
        • n目運算子
        • 關系運算子
        • 邏輯運算子
        • 條件運算子
        • 逗號運算式
    • 7.常見關鍵字
        • 32個常用關鍵字
        • 關鍵字的特性
        • 介紹部分關鍵字
  • 主動技能
    • 1.選擇陳述句
        • 語法
        • 案例分析
    • 2.回圈陳述句
        • 語法
        • 綜合案例
    • 3.函式
        • 語法
        • 綜合案例
    • 4.陣列
        • 定義陣列
        • 訪問陣列元素
        • 綜合案例
    • 5.define定義宏
        • 語法
        • 綜合案例
    • 6.指標
        • 記憶體
        • 指標
    • 7.結構體
        • 創建結構體
        • 使用結構體
        • 結構體指標


被動技能

被動技能學習階段雖然不難,但是是我們今后學習主動技能必不可少的基礎,請各位穩扎穩打,稍安勿躁


1.注釋


注釋的意思

注釋就是寫在程式里但是不會執行的陳述句

注釋的作用

注釋掉暫時不需要的代碼
在難懂的代碼后面寫一些注釋充當“筆記”的作用,讓下一個讀代碼的人能讀懂
記筆記

注釋的寫法

下圖是C++的注釋風格

//

//I love C
//You love C
// We all love C

下圖是C語言的注釋風格

/* */

/*I love C
You love C
 We all love C
 */

2.C語言程式基本框架


下面是一段程式

#include<stdio.h>
int main()
{
	printf("I love C\n");
	return 0;
}

下圖是程式編譯的結果,
也就是說,我們敲了一段代碼,然后程式在控制臺給我們輸出了“I love C”
在這里插入圖片描述
也就是說我們一段程式實際上好像就只執行了這句話

printf("I love C\n");

那么我們就可以大概的知道了,除了這句話以外的東西都是換湯不換藥的

#include<stdio.h>
int main()
{
	//在這里執行陳述句
	return 0;
}

我們把上圖除了注釋以外的部分就叫做C語言的基本框架


我們來逐句講解它們是什么意思

#include<stdio.h>

這一行的作用是引出頭檔案
#include表示的是“引出頭檔案”,后面<>中的就是頭檔案的名字,這些名字的后綴一般是.h
為什么要引出頭檔案呢,問題留著往下看


int main()

這一行的作用是定義主函式
int是函式回傳值的型別,這里是整型
main是函式名,表示這是主函式
()是形式引數,主函式由于默認形式引數為void,void的意思是“無型別”,所以()里是空的


{
    printf("I love C\n");
	return 0;
}

{}一對大括號是一個整體,里面是主函式的內容
printf是一個函式,全稱是print function,作用是把一些東西列印到螢屏上,用法是printf(“要列印的內容”);
但是這個函式我們自己并沒有定義它是怎么運作的,它其實是我們“借來”的,像誰借的呢,就是像我們一開始定義的頭函式stdio.h,stdio的全稱是standard input output,表示一個涵蓋輸入輸出型別函式的檔案,我們參考它,計算機就可以呼叫它內部的別人已經寫好的程式了
我們注意到I love C后面還有一個\n,它是轉義字符,表示換行
return 0;表示這個函式的回傳值是0
我們也注意到了在大括號內的每一行代碼后面都有一個英文輸入法的分號;它表示一行陳述句的結束


3.資料型別

我們寫程式的目的其實是通過借助計算機強大的計算能力來解決生活中的問題,那么我們必須得學會向計算機描述這個問題
比如我的身高是1.75m,體重是65kg,我的國家是China
這些資料各有家門,必須分門別類,它們各自的型別就是資料型別


常見的資料型別

	char
	short
	int
	long
	long long
	float
	double

char-字符資料型別
用來表示字符
eg:ABCabc

short-短整型
int-整形
long-長整型
long long-更長的整形
整形都用來表示整數
eg:1234

float-單精度浮點數
double-雙精度浮點數
浮點數表示小數,浮點的意思就是浮動的小數點
eg:1.75


各種資料型別的大小

介紹運算子sizeof(),它的作用是顯示資料型別的大小(長度)
我們運行一下下面的程式看一下結果(簡約起見結果注釋在行末)

#include<stdio.h>
int main()
{
	printf("%d\n", sizeof(char));//1 
	printf("%d\n", sizeof(short));//2
	printf("%d\n", sizeof(int));//4
	printf("%d\n", sizeof(long));//4
	printf("%d\n", sizeof(long long));//8
	printf("%d\n", sizeof(float));//4
	printf("%d\n", sizeof(double));//8
	return 0;
}

這里的結果是數字,它的量綱是什么呢?答案就是“位元組”
這里引入一下c語言中資料大小的單位
最小的單位是“位元位”,bit
bit是一個二元量,在計算機語言中存放1或者0,表示計算機內部電路的“通”或者“斷”,通過一連串的0/1我們就可以描述出一個整體的電路狀態,這個電路狀態就可以用來表示資訊
我們可以把位元位想象成一個存放0或1的盒子,那么一個位元組(byte)就是8個并排排放的盒子,可以同時存盤8個0/1
以后我們說的資料的長度就是這一排存放0/1的盒子一共有多少個
下面給出單位換算表

1 byte = 8 bit
1 kb = 1024 byte
1 mb = 1024 kb
1 gb = 1024 mb
1 tb = 1024 gb
1 pb = 1024 tb


資料型別的作用

用于創建變數時表示新變數的型別
可以豐富的表達生活中的各種值,讓記憶體的空間利用率更高


4.變數與常量


什么是變數和常量

在程式中值可以繼續變化的量叫做變數,值無法繼續改變的量叫做常量


定義變數的方法

	int age = 20;
	float height = 1.74;
	char ml = 'c';

定義變數時的寫法是
(資料型別)(變數名)=(變數值);
也可以不給初值,但是我們在定義新變數的時候最好養成定義初值的習慣


變數的分類

  • 區域變數
    定義在主函式內部的變數就是區域變數
  • 全域變數
    定義在主函式外部的變數就是全域變數
#include<stdio.h>
int a = 2019;
int main()
{
	int b = 2020;
	{
		int c = 2021;
		printf("%d\n", c);
	}
	printf("%d\n%d\n", a, b);
}

在這里插入圖片描述

a就是全域變數,可以看到a雖然在主函式外定義的但是可以在主函式里面使用
b、c都是區域變數,但是不同的是,b既可以在自己所屬的大括號內使用,又可以在c所屬的大括號內使用,而c只能在自己所屬的大括號內使用

#include<stdio.h>
int a = 2019;
int main()
{
	int b = 2020;
	{
		int c = 2021;
		printf("%d\n", b);
	}
	//printf("%d\n%d\n", a, c);
}

上圖結果
在這里插入圖片描述

#include<stdio.h>
int a = 2019;
int main()
{
	int b = 2020;
	{
		int c = 2021;
		//printf("%d\n", b);
	}
	printf("%d\n%d\n", a, c);
}

上圖結果
在這里插入圖片描述


變數的作用域和生命周期

  • 作用域
    變數能在哪里使用哪里就是變數的作用域
  • 生命周期
    變數創建到銷毀的時間段
    eg:
    全域變數的作用域是整個工程
    生命周期就是程式的生命周期
    eg:
    區域變數的作用域是變數所在的區域范圍,一般是所屬的{}內部
    進作用域生命周期開始,出作用域生命周期結束
  • 補充知識:全域變數在相同解決方案不同源.c檔案的使用
    在同解決方案下另一源檔案中使用全域變數需要用extern宣告其為外部變數
    在這里插入圖片描述
    在這里插入圖片描述

常量的分類

  • 字面常量
    比如程式中出現的數字或者字符:123 1.75 12f
    eg:
#include<stdio.h>
int main()
{
	int a = 10;
	printf("%d", a);
}

10就是字面常量

  • const修飾的常變數
    具有常屬性(不能變值)的變數
    eg:
#include<stdio.h>
int main()
{
	const int a = 10;
	a = 20;
	printf("%d", a);
}

在這里插入圖片描述
從上圖可知const定義的變數不可變值

#include<stdio.h>
int main()
{
	const int a = 10;
	int b[a] = { 0 };
	printf("%d", b[0]);
}

在這里插入圖片描述
從上圖可知a仍然是變數(陣列大小必須是常量)

  • #define 定義的識別符號常量
    直接永久賦值
    既可以在主函式外部也可以在內部定義
    在這里插入圖片描述

  • 列舉常量

#include<stdio.h>
enum Sex
{
	MALE,
    FEMALE,
    SECRET
};
int main()
{
	enum Sex a = SECRET;
	printf("%d", a);
	return 0;
}

結果是2,因為列舉常量未賦值時按序號賦默認值

#include<stdio.h>
enum Sex
{
	MALE=3,
    FEMALE=5,
    SECRET=123
};
int main()
{
	enum Sex a = SECRET;
	printf("%d", a);
	return 0;
}

結果是123,因為賦值為123

#include<stdio.h>
enum Sex
{
	MALE=3,
    FEMALE=5,
    SECRET
};
int main()
{
	enum Sex a = SECRET;
	printf("%d", a);
	return 0;
}

結果是6,因為SECRET上一個列舉常量FEMALE是5,所以按照序號,未賦值列舉常量SECRET是6

總結規律如下:
賦值列舉常量按所賦值定義
未賦值列舉常量按序號定義


5.字符、字串、轉義字符


字符

單個字母或符號
在這里插入圖片描述
b就是字符


字串

由雙引號引起的一串字符
在這里插入圖片描述
I love C\n就是字串


轉義字符

不是原本含義的,有特殊作用的字符組合
在這里插入圖片描述
還是這個程式,\n的意思不是“斜杠和n”,而是換行的意思,\n就是轉義字符
下面給出常見轉義字符
騙你的,自己查去,多試試就會用了

要求是認識常見的轉義字符,會數出含有轉義字符的字串的長度
比如下面這段程式
在這里插入圖片描述

補充知識:strlen函式
strlen–string length
用來計算字串的長度

c : e s t 8 e s t . c共11個字符
兩個\t是兩個轉義字符
一個\32是一個轉義字符
一共14個字符


字串的結束標志——字符終止符\0

\0是一個轉義字符,表示字串的終止,計算字串長度的時候作為結束的標識,不算做字串的內容,沒有長度
看這段程式
在這里插入圖片描述
總結:
" "內字串默認存在\0作為結束標志
’ ’ 內字符必須手動添加\0作為結束標志,否則會產生亂碼,比如上圖的arr2


6.運算子

用來處理變數、常量、字符和它們之間關系的符號


算數運算子

  • **加 +
  • 減 -
  • 乘 *
  • 除 /
  • 取余 %**
    (a%b=a除以b的余數)

移位運算子

  • 左移運算子 <<
    將物件的二進制位向左移動一位
  • 右移運算子 >>
    將物件的二進制位向右移動一位

簡單介紹:
比如1的二進制位是00000000000000000000000000000001一共32個數字
在總數字個數不變的情況下把這段數字向左移動一位,缺位補0
那么
00000000000000000000000000000001
就變成了
00000000000000000000000000000010
也就是二進制的數字2
寫成代碼的形式就是

#include<stdio.h>
int main()
{
	int a = 1;
	int b = a << 1;
	printf("%d", b);
	return 0;
}

在這里插入圖片描述


位運算子

  • 與 & (同真為真 其余為假)
  • 或 ^(同假為假 其余為真)
  • 非 |(非假為真 非真為假)

賦值運算子與復合賦值符

  • 賦值運算子 = (將右值賦給左邊)
  • 復合賦值符 += -= = /= &= ^= |= >>= <<=
    (a x= b 等價于 a=a x b ,x是運算子)

單目運算子

  • 邏輯反 !(!非0=0,!0=1)
  • 負值 -(取相反數)
  • 正值 +
  • 取地址 & (見本篇指標部分)
  • 以位元組為單位計算型別長度 sizeof
    見程式“列印陣列的個數”
#include<stdio.h>
int main()
{
	int arr[] = { 0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("%d", sz);
	return 0;
}
  • 對數二進制按位取反 ~
#include<stdio.h>
int main()
{
	int a = 0;
	printf("%d", ~a);
	return 0;
}

輸出的值是-1
為什么呢?
這里引入C語言中原碼反碼補碼的概念

C語言中的二進制整數的第一位是符號位,0代表正數,1代表負數

  • 正整數的原反補碼相同
  • 負整數的原碼代表本身的值
    設已知負整數的原碼 則負整數的反碼是原碼符號位不動其他位按位取反(0變1,1變0)
    補碼是反碼+1

接著看上面的程式,
a=0,也就是說a的原碼是
00000000000000000000000000000000
那么~a就是
11111111111111111111111111111111
整數在記憶體中儲存的是補碼
也就是說列印出來的~a的補碼是
11111111111111111111111111111111
那么~a的反碼是(補碼-1)
11111111111111111111111111111110
~a的原碼是(反碼除了符號位按位取反)
10000000000000000000000000000001

  • 強制型別轉換 (型別)
    比如我們打出下面這句話
int a = 3.14;

輸出的時候會報錯,告訴我們資料型別不對的時候會丟失資料
那我們怎么才能強制讓一個浮點數按照整形輸出呢

int a =int3.14;
#include<stdio.h>
int main()
{
	int a = (int) 3.14;
	printf("%d", a);
	return 0;
}

結果是3

  • 前置++和后置++
    ++在前,先++,再參與本行運算
    ++在后,先參與本行運算,再++
#include<stdio.h>
int main()
{
	int a = 0;
	int b = ++a;
	printf("%d\n", b);
	int c = 0;
	int d = c++;
	printf("%d\n", d);
	return 0;
}

++a——a先加一再參與b的賦值運算
c++——c先參與d的賦值運算再加一
上圖結果是
1
0


n目運算子

雙目運算子:操作兩個物件的運算子
三目運算子:操作三個物件的運算子


關系運算子

測驗是否大于 >
測驗是否大于等于 >=
測驗是否小于 <
測驗是否小于等于 <=
測驗是否不等于 !=
測驗是否等于 ==
是結果為1,否結果為0


邏輯運算子

  • 邏輯與 &&
    “并且”的意思
    同真(非0)為1,其余為0
  • 邏輯或 ||
    “或者”的意思
    同假(0)為0,其余為1

條件運算子

  • a ? b : c
    a真為b,a假為c

逗號運算式

逗號隔開的一串運算式

#include<stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	int c = 3;
	int d = (a = b - 1, b = c + 2, c = a - b);
	printf("%d", d);
	return 0;
}

整個逗號運算式表示的并列陳述句,從左向右進行計算
整個運算式的結果是最后一句計算結束的結果
上圖結果為-4


7.常見關鍵字


32個常用關鍵字

C語言中一共有32個常見關鍵字
給出32個關鍵字

auto break case char
const continue default do
double else enum extern
float for goto if
int long register return
short signed sizeof static
struct switch typedef union
unsigned void volatile while


關鍵字的特性

關鍵字是C語言自帶的語法,不能自己創建關鍵字
在C語言中,關鍵字不能用作變數名


介紹部分關鍵字

節選部分講解,其余的之前已經講過或今后會慢慢接觸

  • aoto
    “自動的”
    每個區域變數都是aotu修飾的,所以經常省略不寫
  • register
    暫存器關鍵字
  • 什么是暫存器?
    簡單理解,暫存器就是運行速度很快,空間很小的儲存資料的東西
    它比記憶體快的多,所以使用暫存器可以大大的提高資料呼叫速度

所以,被大量頻繁使用的資料,就可以放在暫存器變數中,提升效率
但是現在的許多編譯器已經能夠自動識別這種資料并把它們放進暫存器,所以register關鍵字現實使用意義不大

  • typedef
    型別重定義
    可以給型別重新起名字,用于簡化代碼
#include<stdio.h>
typedef unsigned int u_int;
int main()
{
	u_int d = -100;
	printf("%d", d);
	return 0;
}

typedef 舊型別名 新型別名 ;

  • static
    靜態的
  1. static修飾區域變數
    static修飾的區域變數出作用域后不會銷毀
#include<stdio.h>
void Add()
{
	static int a = 1;
	a++;
	printf("%d ", a);
}

int main()
{
	int i = 0;
	while (i < 10)
	{
		Add();
		i++;
	}
	return 0;
}

第一次呼叫Add函式的時候,a=2
由于是static定義,a出作用域未被銷毀,a仍然被定義且值為2
第二次呼叫Add函式的時候,a = a+1 = 2+1 = 3,以此類推

static修飾的區域變數,本質上是改變了變數的存盤型別
把堆疊區的區域變數分配到了靜態區
讓區域變數的生命周期延長到了全域變數

  1. static修飾全域變數
    static修飾全域變數使得全域變數只能在自己的源檔案中使用,不再能通過extern宣告參考跨源檔案的全域變數

  2. static修飾函式
    static修飾函式使得函式只能在自己的源檔案中被呼叫,不再能通過extern宣告參考跨源檔案的函式(與static修飾全域變數作用類似)

static修飾全域變數和函式,本質上是將它們的外連接屬性變成了內連接屬性,使得它們不再能在全域被參考或呼叫


注意:
define 、include等不是關鍵字,是預處理指令,以后會介紹


主動技能

恭喜你已經習得C語言的各種被動技能,但是光有被動我們還只是一個任人宰割的小兵,接下來讓我們開始學習C語言的主動技能吧,它們是C語言的重頭戲,效果十分強勁,是我們以后征戰沙場的得力助手,今后會繼續就每一個主動技能做講解,今天我們就先和它們打個照面,交個朋友吧!


1.選擇陳述句

我們在生活中常常會面對各種各樣的選擇,有時候會陷入兩難的境地
那么,如何向計算機描述這種選擇的情況呢?接下來我們引入第一個主動技能——選擇陳述句


語法

(由于是第零篇,僅介紹if-else陳述句)

if(條件)
{
條件為真的時候執行的陳述句;
}
else
{
條件為假的時候執行的陳述句;
}


案例分析

看下面這段程式

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	int a = 0;
	printf("你想要一個女朋友嗎\n");
	scanf("%d", &a);
	if (a)
	{
		printf("恭喜你脫單\n");
	}
	else
	{
		printf("單身萬歲\n");
	}
	return 0;
}

程式的意思就是:
你想要女朋友嗎
輸入1,就會脫單
在這里插入圖片描述
輸入0,就繼續單身
在這里插入圖片描述
這樣就是做出了一個選擇

接下來讓我們逐句解讀一下

#define _CRT_SECURE_NO_WARNINGS 1

這句話是干啥的呢?我們暫時只需要知道這句話的作用是保證呼叫scanf函式的時候系統不會報錯的就行了,如果你在運行程式的時候在出現scanf報錯的情況,就請先加上它吧
由于講過了程式框架,接下來我們就只看程式主體部分

	int a = 0;

定義一個新的變數a并且初始化,初值為0

	printf("你想要一個女朋友嗎\n");

列印“你想要一個女朋友嗎”這句話并且換行

	scanf("%d", &a);

引入函式scanf
作用是把從鍵盤上輸入的值賦值給指定變數
我們可以發現scanf函式和printf函式很像,唯一的不同就是在變數名前面必須加上一個取地址符&
這句話的意思從鍵盤接受一個數并且把它賦值給a

	if (a)
	{
		printf("恭喜你脫單\n");
	}
	else
	{
		printf("單身萬歲\n");
	}

判斷a的值,如果a的值是真(非零),就執行if下的陳述句:列印“恭喜你脫單”,如果a的值是零,就列印“單身萬歲”


2.回圈陳述句

計算機最強大的地方就是可以把同一個步驟在極短的時間內不知疲倦的重復成千上萬次,我們利用這個強大特性的陳述句就是回圈陳述句,接下來引入第二個主動技能——回圈陳述句


語法

(由于是第零篇,僅介紹while陳述句)

while(條件)
{
條件為真時重復執行的陳述句;
}

條件為假則跳出回圈


綜合案例

“編程之路”

#include<stdio.h>
int main()
{
	int input = 0;
	printf("歡迎來到編程的世界\n");
	printf("你要好好學習嗎?(1/0):");
	scanf("%d", &input);
	if (input == 1)
	{
	printf("好作業\n");
	int day = 0;
	int line = 0;
	printf("開始編程\n");
	scanf("%d", &day);
	while (line < day)
	{
		printf("堅持敲代碼 堅持天數:%d\n", line);
		line++;
	}
	if (line >= 20000)
		printf("好offer\n");
	else
		printf("墜入愛河無心學習\n");
	}
	else
		printf("回家種地\n");
	
	return 0;
}

提示:使用了if的嵌套和while回圈,并且使用if判斷條件跳出回圈


3.函式

我們在初中就學過函式,比如這樣一個函式
f1(x)=2x
它的意思是把物件變成自身的二倍,你可能覺得這個函式并不能起到什么簡化的作用,再看這一個函式
f2(x,y)=(x3+y3)/(x3-y3)
如果我們每次使用都把后面這一串運算表示出來就太麻煩了,我們可以直接用f2(x,y)來表示
同理,c語言中我們可以用已經寫好的函式來極大的幫助我們簡化主函式,讓我們的代碼更加清晰,層次分明,可讀性強


語法

函式回傳值型別 函式名(形式引數型別 形式引數名)
{
形式引數參與的陳述句;
return 回傳值;
}


綜合案例

“比大小”

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int Cpa(int a,int b)
{
	if (a > =  b)
	{
		return a;
	}
	else
	{
		return b;
	}	
}
int main()
{
	int x = 0;
	int y = 0;
	int z = 0;
	scanf("%d%d", &x, &y);
	z = Cpa(x, y);
	printf("%d", z);
	return 0;
}

提示:注意定義函式的寫法和呼叫函式的寫法,注意形式引數和實際引數不要弄混


4.陣列

要想存盤5個數,怎么存盤?你可能覺得我定義5個變數abcde就好了,那50個數呢?500個數呢?
引出C語言中陣列的概念:一組相同型別元素的集合


定義陣列

陣列資料型別 陣列名[陣列元素個數] = {陣列元素1,陣列元素2};


訪問陣列元素

陣列名[下標]

#include<stdio.h>
int main()
{
	int i = 0;
	int arr[10] = { 1 };
	printf("%d", arr[0]);
	return 0;
}

下標是按照0、1、2、3、4…的順序排列的,所以第一個元素的下標是0


綜合案例

列印陣列中所有的元素

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n", arr[0]);
	int i = 0;
	while (i < 10)
	{
		printf("%d\n", arr[i]);
		i++;
	}
	return 0;
}

5.define定義宏


語法

#defne 宏名(形式引數)(宏內容)


綜合案例

#include<stdio.h>
#define Add(x,y) (x+y)
int main()
{
	printf("%d", 5*Add(2, 3));
	return 0;
}

上圖結果為25
define定義宏本質就是替換,作用和函式類似


6.指標

指標是C語言的靈魂,是當之無愧的大招


記憶體

記憶體是計算機中用來儲存資料的空間
就像是一個個空房子
為了方便我們拜訪和管理它們,每個房子都有自己的地址
在這里插入圖片描述

  • 記憶體是怎么編號的?
    32位、64位——指的是32/64根地址線——物理線——通電——1/0——產生了電信號
    電信號就能夠存盤數字資訊
    以32位的機器舉例
    二進制數字

    00000000000000000000000000000000

    11111111111111111111111111111111
    一共232個數字
    可以用來當作232個房間的地址
    我們就把這232個房間的地址叫做地址
    也就是說我們可以管理232個記憶體單元

  • 最小的記憶體單元是多大空間?
    假如最小的記憶體空間是bit
    1GB=210MB=220KB=230Byte=233bit
    也就是說以bit為最小單位的232個地址可以管理0.5GB的記憶體
    這樣的話管理的空間就太小了,不太合適
    所以我們規定

最小的記憶體單元是位元組(byte)

這樣232個地址就可以管理4GB的記憶體


指標

承接上面記憶體的內容,如果我們想要定義一個int型變數,將給它分配4個位元組的空間
在這里插入圖片描述

  • 取地址
    引入取地址符號&
    如果我們定義是四個位元組的變數,雖然它每個位元組都會分配地址,但是取地址就是取出這個變數第一個位元組的地址
    在這里插入圖片描述
    %p是列印地址的型別
  • 指標變數(存地址)
    專門定義出來用來存放地址的變數叫做指標變數,簡稱指標
int main()
{
	int a = 10;
	int* pa = &a;
	return 0;
}

*表示pa是指標變數,int說明pa執行的物件int型別的
再比如char型別的指標變數就是char *

int main()
{
	char ch = 'a';
	char* pa = &ch;
	return 0;
}
  • 訪問地址
int main()
{
	int a = 10;
	int* pa = &a;
	*pa = 20;
	return 0;
}

*解參考操作,*pa就是通過pa里面存放的地址找到a

*pa = 20;

這句話就是通過指標pa操作了指標指向的物件a,將a重新賦值為20
由此我們可以總結:
指標就是地址

  • 指標變數的大小
    指標是用來存放地址的,而在32位機器上地址是32位的二進制數,大小是32bit,而地址有多大就決定了指標變數的大小
    所以指標變數的大小就是32bit
    也就是4個位元組
    (在64位機器上就是8個位元組)

7.結構體

結構體可以通過不同的維度來描述復雜物件


創建結構體

創建結構體可以理解為創建了一個新的復合資料型別

struct 結構體名
{
定義成員變數1;
定義成員變數2;
};

struct Stu
{
	char Name[20];
	int age;
	int height;
	double score;
};

使用結構體

#include<stdio.h>
struct Stu
{
	char Name[20];
	int age;
	float height;
	double score;
};
int main()
{
	struct Stu s = { "小白",18,1.74,85.5 };
	printf("%s %d %f %lf", s.Name, s.age, s.height, s.score);
	return 0;
}
struct Stu s = { "小白",18,1.74,85.5 };

s是結構體變數名
{}內部是結構體各項的內容

printf("%s %d %f %lf", s.Name, s.age, s.height, s.score);

s.Name中的點運算子是用來訪問結構體成員

結構體變數 . 結構體成員


結構體指標

#include<stdio.h>
struct Stu
{
	char Name[20];
	int age;
	float height;
	double score;
};
int main()
{
	struct Stu s = { "小白",18,1.74,85.5 };
	struct Stu* pa = &s;
	printf("%s %d %f %lf", (*pa).Name, (*pa).age, (*pa).height, (*pa).score);
	return 0;
}

pa就是結構體指標
但是這種寫法有點啰嗦,看下面這種寫法

#include<stdio.h>
struct Stu
{
	char Name[20];
	int age;
	float height;
	double score;
};
int main()
{
	struct Stu s = { "小白",18,1.74,85.5 };
	struct Stu* pa = &s;
	printf("%s %d %f %lf", pa->Name, pa->age, pa->height, pa->score);
	return 0;
}

->就是箭頭運算子
語法是

結構體指標->結構體成員名


至此為止,初識C語言結束,我們已經不再是霧里看花的門外漢,真正走上了編程之路,但是這只是剛剛完成了定級賽,只是我們從青銅到王者的起點,
好戲剛剛開始,諸位盡請期待,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/273769.html

標籤:其他

上一篇:華為杯題A細胞分解

下一篇:深入 Java 原始碼來剖析 hashCode,從此菜不再是原罪

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more