翁恺老师的c语言学习笔记
翁愷老師講的超級好,人也超級可愛,b站的彈幕也很可愛。
運算符
前綴后綴
關系運算符(比較)
所有關系運算符的優先級比算術運算符的低,比賦值運算符的高。
e.g. 7>=3+4
int a=r>0
判斷是否相等的 == 和 != 的優先級比其他的低,而連續的關系運算是從左到右進行的。
5>3 == 6>4
6>5>4 結果為0
a == b == 6
a == b > 0
級聯的if-else
if()
str;
else if()
str;
else
str;
(對齊寫,格式好看)
多路分支switch-case
case是開始的地方,break是結束的地方。
隨機數 srand(time(0))
time是C語言獲取當前系統時間的函數,以秒作單位,代表當前時間自Unix標準時間戳(1970年1月1日0點0分0秒,GMT)經過了多少秒。
形式為time_t time(time_t * t);
該函數提供兩種返回方式,返回值,和指針參數。
可以根據需要選擇。當參數t為空指針(NULL)時,只返回值。
而NULL的定義是(void *) 0, 所以time(0)也就是time(NULL)的另一種寫法,表示只通過返回值獲取時間值。
如果得到的數太大,則可以a%100,范圍會在0~99。
break和continue 從嵌套的循環中跳出
break和continue只能對他所在的那層循環使用。怎么跳出三重循環?(1)接力break:設置標志,滿足標志為1時,每個循環都有一個break;(2)goto:goto out; out: 程序跳到out所在位置。
-1的n次方
如果在循環中,可以初始sign=1,循環中每次sign=-sign。
整數分解
(1)先逆序(c*10+b)*10+a再從右開始輸出,但不適合700這種末尾有0的數字,結果只為7,而不是700。
(2)先計算這個整數的位數cnt,構造mask=pow(10,cnt-1),d=a/mask, a=a%mask, mask/=10,循環以mask為判定條件。注意邊界值和特殊值。
左對齊 %-10d
sizeof() 某個類型或變量占據的字節數
sizeof是靜態運算符,它的結果在編譯時刻就決定了;
不要在sizeof的括號里做運算,這些運算不會做的。
整數類型
●char: 1字節(8比特) -128~127(默認補碼)
●short: 2字節 -32768~32767
●int: 取決于編譯器(CPU) ,通常的意義是“1個字”(字長)-232-1~232-1-1
●long:取決于編譯器(CPU), 通常的意義是“1個字”
●long long: 8字節
字長:
補碼
補碼加原碼得到溢出的0。對于-a,其補碼就是(1)0-a,實際是2n- a,n是這種類型的位數。
8位:
00000000 -> 0
11111111 ~ 10000000 -> -1 ~ -128
00000001 ~ 01111111 -> 1 ~127
unsigned
如果一個字面量常數想要表達自己是unsigned,可以
在后面加u或U,e.g.255U。
用I或L表示long(long)。
*unsigned的初衷并非擴展數能表達的范圍,而是為
了做純二進制運算,主要是為了移位。
整數的輸入輸出
只有兩種形式: int或long long
%d: int
%u: unsigned
%ld: long long
%lu: unsigned long long
8進制和16進制
一個以0開始的數字字面量是8進制
一個以0x開始的數字字面量是16進制
%o用于8進制,%x用于16進制
8進制和16進制只是如何把數字表達為字符串,與內部如何表達數字無關
浮點類型
浮點的輸入輸出
計算機能表示的數是離散的,導致某些數不能精確表示,只能用相近的數表示。
printf輸出inf表示超過范圍的浮點數:+∞、-∞
printf輸出nan表示不存在的浮點數
inf: -12.0/0.0 +12.0/0.0(浮點數的設定可以) 12/0(編譯不通過)
nan:0.0/0.0
帶小數點的字面量是double而非float,float需要用f或F后綴來表明身份。
怎么判斷兩個浮點數是否相等:
f1==f2可能失敗
fabs(f1-f2) < 1e-12 (float用1e-8就可以了)
選擇浮點類型:
如果沒有特殊需要,只使用double,
現代CPU能直接對double做硬件運算。
算錢錢
不能用浮點數算錢錢,可以看作整數(元角分)來做運算。
強制類型轉換
(int)3.9001
(int)(1.0/3.0) 強制類型轉換的優先級高于四則運算。
a<b<c
像4<x< 6這樣的式子,不是C能正確計算的式子,因為4< x的
結果是一個邏輯值(0或1)。
優先級
短路
所以,不要把賦值,包括復合賦值組合進表達式。
參數傳遞
C語言在調用函數時,永遠只能 傳值(而不是變量) 給函數。
傳值:每個函數有自己的變量空間,參數也位于這個獨立的空間中,和其他函數沒有關系。
本地變量(塊)
本地變量是定義在塊內的,它可以是定義在函數的塊內,也可以定義在語句的塊內,甚至可以隨便拉一 對大括號來定義變量。
程序運行進入這個塊之前,其中的變量不存在,離開這個塊,其中的變量就消失了。
塊外面定義的變量在里面仍然有效。
塊里面定義了和外面同名的變量則掩蓋了外面的。
main函數
return 0 是有意義的,有些人需要這個結果,表示正確執行。
數組下標
聲明數組時,c99以前是只能是常量,c99是支持下標是變量的,只是vs2015不支持。但數量一旦確定就不再更改。
數組初始化
數組的大小
sizeof(a)給出的是整個數組所占據的大小,單位是字節。
數組大小:sizeof(a)/sizeof(a[0])
數組作為函數參數時
數組作為函數參數時,往往必須再用另一個參數來傳入數組的大小。
數組作為函數的參數時: 不能在[ ]中給出數組的大小,不能再利用sizeof來計算數組的元素個數!
構造素數的多種方法
數組例子:素數
二維數組的初始化
32.取地址運算
&運算符取得變量的地址。它的操作數必須是變量。
指針
指針變量就是記錄地址的變量。
訪問那個地址上的變量 * :
* 是一個單目運算符,用來訪問指針的值所表示的地址上的變量,可以做右值也可以做左值。
左值
指針最常見的錯誤:定義了指針變量,還沒有指向任何變量,就開始使用指針。
int *p;
*p=10; 錯誤,要先給p賦予值,即它指向的地址。
指針和const
指針本身和所指的變量都可能const。
指針是const:
所指是const:
const數組
●數組變量是const的指針,所以不能被賦值。
int b[]=a;//錯誤
int a[] <==> int* const a=…
p+1
p+1相當于p+sizeof(類型)。
給一個指針加1表示要讓指針指向下一個變量。
那么*(p+n) <-> a[n]
*p++
0地址
動態內存分配
C99可以用變量做數組定義的大小,C99之前呢?
如果內存分配失敗會返回0或NULL。
free只能還申請來的空間的首地址。
字符數組:char word[] = {'H','e','l','l',‘o','!'};
字符串:char word[] = {'H','e','l','l', 'o','!','\0'};
字符串:
字符串變量:
\0不是字符串的一部分但是占據數組的一個字節。
C語言的字符串是以字符數組的形態存在的,不能用運算符對字符串做運算,通過數組的方式可以遍歷字符串。
唯一特殊的地方是字符串字面量可以用來初始化字符數組。
以及標準庫提供了一系列字符串函數。
字符串常量:
指針還是數組:
如果要構造一個字符串->數組
如果要處理一個字符串->指針
在%和s之間的數字表示最多允許讀入的字符的數量,這個數字應該比數組的大小小1。
vs中不支持%7s這種寫法,應
常見錯誤:
指針不知道指向哪里了。
putchar:
getchar:
strlen:返回s的字符串長度(不包括結尾的0)。
strcmp:比較兩個字符串,返回:
●0: s1==s2
●1: s1>s2
●-1: s1<s2
strcpy:
strcat:
安全問題:strcpy和strcat都可能出現安全問題,如果目的地沒有足夠的空間?
安全版本:
字符串中找字符:
字符串中找字符串:
聲明:enum color c; //enum不能少
小技巧:
這樣需要遍歷所有的枚舉量或者需要建立一個用枚舉量做下標的數組的時候就很方便了。
聲明枚舉量的時候可以指定值。
如果有意義上排比的名字,用枚舉比const int方便。
枚舉比宏(macro) 好,因為枚舉有int類型。
結構可以做賦值運算,s1=s2。
結構作為函數參數:
整個結構可以作為參數的值傳入函數;這時候是在函數內新建一個結構變量, 并復制調用者的結構的值;也可以返回一個結構;這與數組完全不同。
輸入結構:
沒有直接的方式可以一次scanf一個結構。
一個小問題:
結構體是函數參數時,傳入函數的是外面那個結構的克隆體,而不是指針。那么主函數怎么得到結構體的值呢?(1)在這個調用的函數中,完全可以創建一個臨時的結構變量,然后把這個結構返回給調用者。return s;
(2)(更好)結構指針作為參數。但是函數還是可以寫成返回這個指針,即函數是struct date* 類型,這樣可以方便進入別的計算。
用->表示指針所指的結構變量中的成員。
自定義數據類型typedef
C語言提供了一個叫做typedef的功能來聲明一個已有的數據類型的新名字。
聯合union
存儲:
所有的成員共享一個空間;同一時間只有一個成員是有效的;union的大小是其最大的成員。
sizeof (union)=sizeof (每個成員)的最大值
初始化:
對第一個成員做初始化。
_func_ ,輸出用%s ,表示當前函數的名字。
全局變量
初始化:
沒有做初始化的全局變量會得到0值;指針會得到NULL值;只能用編譯時刻已知的值來初始化全局變量;它們的初始化發生在main函數之前。
被隱藏的全局變量:
如果函數內部存在與全局變量同名的變量,則全局變
量被隱藏。
靜態本地變量static:能在函數結束后繼續保有原值的本地變量
在本地變量定義時加上static修飾符就成為靜態本地變量;
當函數離開的時候,靜態本地變量會繼續存在并保持其值;
靜態本地變量的初始化只會在第一次進入這個函數時做,以后進入函數時會保持上次離開時的值。
實質:
靜態本地變量實際上是特殊的全局變量,它們位于相同的內存區域。靜態本地變量具有全局的生存期,函數內的局部作用域,static在這里的意思是局部作用域(本地可訪問)。
返回指針的函數
●返回本地變量的地址是危險的,已經不可控。
●返回全局變量或靜態本地變量的地址是安全的。
●返回在函數內malloc的內存是安全的,但是容易造成問題。
●最好的做法是返回傳入的指針。
tips:
不要使用全局變量來在函數間傳遞參數和結果;
使用全局變量和靜態本地變量的函數是線程不安全的。
#開頭的是編譯預處理指令,它們不是C語言的成分,但是C語言程序離不開它們。
#define用來定義一個宏。
預定義的宏:
一切都要括號:
●整個值要括號
●參數出現的每個地方都要括號
為什么?
注意:#define 結束一定不要加分號。
●在使用和定義這個函數的地方都應該#include這個頭文件。
●一般的做法就是任何.c都有對應的同名的.h,把所有對外公開的函數的原型和全局變量的聲明都放進去。
不對外公開的函數:
在.h文件中加入變量的聲明。
這個有疑惑(只把聲明寫在頭文件)就去收藏夾(小疑惑)。
標準頭文件結構:
p112 聲明
printf:%[flags][width][.prec][hlL]type
所以這里的6可以替換為一個變量。
%n:
scanf:%[flag]type
文件輸入輸出
打開文件的標準代碼:
按位異或
左移<<
右移>>:
可變數組
可變數組的缺陷:1. 擴容時每次復制浪費時間;2. 萬一想要擴容,卻沒有更大的內存了。由此引入鏈表。
在p125鏈表的函數中注意的點
指針做函數參數時,在函數內部做運算時,指針所指的內容可以被修改,但修改指針本身(使指針指向別處)不會影響外部的指針。
p125鏈表的函數
任何在“->”左邊的指針必須check,是否為空。
圖形交互
總結
以上是生活随笔為你收集整理的翁恺老师的c语言学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一种通感一体化的信号设计与性能分析
- 下一篇: jquery 获取系统默认年份_你没有看