快速上手c語言

快速上手c語言

  • 快速上手c語言
    • 關于學c語言的一些信息雜談
    • 第一個C語言程序
      • 通過命令行運行c程序
      • Dev-c++5.11
      • Visual Studio系列產品
    • 數據類型
    • 變量、常量
      • 定義變量的方法
      • 變量的命名
      • 變量的分類
      • 變量的使用
      • 變量的作用域和生命周期
      • 常量
    • 操作符簡單介紹
    • 語句
      • 選擇語句
      • 循環語句
    • 數組
      • 數組定義
      • 數組的下標
      • 數組簡單使用
      • 變長數組的概念
    • 字符串和轉義字符
      • 字符串
      • 轉義字符
    • 注釋
    • 函數
      • 關于scanf的返回值
    • 常見關鍵字
    • #define 定義常量和宏
    • 指針
      • 內存
      • 地址的產生(可跳過)
      • 變量的地址
    • 結構體

快速上手c語言

在看懂c語言的基礎上,再學會如何使用。

同理,在學會使用c語言的基礎上,再進行語法和細節上的拓展。

因此本篇的目的是基本了解C語言的基礎知識,對C語言有一個大概的認識。

每個知識點就是簡單認識,不做詳細講解,后期會進行補充。

關于學c語言的一些信息雜談

僅為個人平時聽別人說話總結的東西,可跳過:

  1. 開始學c,都是先從簡單概念介紹編譯環境的搭建開始,會用就行,用熟后再學內部的東西。學其他編程語言(也可以是交流的語言)也是這樣。
  2. 寫博客是表示你愿意向其他人分享知識,同時也是知識點的總結,寫其他博客也一樣。在面試時可以加深面試官的印象。
  3. 寫完的代碼可以上傳git。git可以是gitee(國內),也可以是githup(國外)。一般用gitee就夠,也可以用githup。這個也是可以在面試時加印象分。
  4. 語言,我暫時理解為兩個或多個對象之間的交流。比如人與人交流可以通過漢語、英語等。相對應的,人與計算機交流可以通過c語言、c++、Java等程序設計語言和開發環境。
  5. 學好編程不僅是學好c語言,這些都可以提升編程的能力,推薦去學:
    • 計算機語言,推薦學完c語言和一門面向對象的語言(比如c++)后再去學其他語言,會有全新的認識。
    • 算法和數據結構。
    • 操作系統。
    • 計算機網絡。
    • 項目實戰。
    • 數據庫-MySQL。
  6. c語言廣泛用于底層開發。比如,一個電腦剛買來的時候是一個硬件(稱之為里面裝有電路板的方塊更恰當),這個硬件裝了操作系統比如windows 10,Linux等。
    操作系統之上的稱之為上層軟件。這里用一張圖大致描繪電腦的結構:
    請添加圖片描述

c語言更擅長做底層軟件開發,在嵌入式開發、單片機開發中應用廣泛,但c語言也可以做上層軟件。其中Linux內核就是用c語言寫出來的(不懂沒關系,以后會懂)。

  1. 計算機語言的發展:
    請添加圖片描述

  2. 編程可以狹義的稱之為寫代碼。寫代碼是為了利用計算機解決生活中的問題。

  3. c語言誕生的時候,c語言在不同人(公司)手上各自設有自己的標準。這就使得
    A公司寫的代碼無法在B公司用。于是C語言的國際標準統一,也就是出現統一的標準。
    ANSI C是最早的標準,當時稱它為C89,后來不斷根據需求增添和修改功能。目前的習慣是在C后面加年份的最后2位來指代這個標準。
    C11之前的標準都是在20世紀末發布,C11是2011發布的最新標準。

請添加圖片描述

  1. c語言還需要通過編譯器翻譯成計算機看的懂的語言,計算機才能去做事。
    常見的c語言編譯器:

    • Microsoft Visual Studio系列(簡稱vs),推薦使用vs2019,版本太舊會出現BUG或版本不兼容,太新的話微軟公司做的封裝太嚴實,不利于新人學習c語言。
      vs用的編譯器是MSVC。
      vs集結編輯器、編譯器、調試器和別的東西,集結寫源代碼文本、編譯和運行為一體,稱這種大成集合體為集成開發環境。英文縮寫:IDE。
      類似的產品還有Visual Studio Code(簡稱vscode)只是用來寫代碼的編輯器,需要裝很多插件才能用。
    • Linux平臺下的gcc。windows也有gcc,主要是Dev-c++和vscode用。
    • 蘋果維護的clang。
  2. c語言是一門通用計算機編程語言,廣泛應用于底層開發。C語言的設計目標是提供一種能以簡易的方式編譯、處理低級存儲器、產生少量的機器碼以及不需要任何運行環境支持便能運行的編程語言。

  3. 盡管c語言提供了許多低級處理的功能,但仍然保持著良好跨平臺的特性,以一個標準規格寫出的c語言程序可在許多電腦平臺上進行編譯,甚至包含一些嵌入式處理器(單片機或稱MCU)以及超級電腦等作業平臺。

  4. 二十世紀八十年代,為了避免各開發廠商用的c語言語法產生差異,由美國國家標準局為c語言制定了一套完整的美國國家標準語法,稱為ANSI C,作為c語言最初的標準。 2011年12月8日,國際標準化組織(ISO)和國際電工委員會(IEC)發布的C11標準是c語言的第三個官方標準,也是c語言的最新標準,該標準更好的支持了漢字函數名和漢字標識符,一定程度上實現了漢字編程。

  5. C語言是一門面向過程的計算機編程語言,與C++,Java等面向對象的編程語言有所不同。其編譯器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。
    我的c語言和c++的學習主要的環境是GCC(為方便我會寫成gcc)和MSVC(為方便我會寫成vs或vs2019)。

  6. 推薦書籍:

    • 初學c語言和初學c++階段:
      《C和指針》
      《高質量的C/C++編程指南》
      《C語言深度剖析》
      《數據結構》嚴蔚敏(c語言版)殷人昆(c++版)
      《程序員的自我修養》
      《C陷阱與缺陷》

    • 對c++有一定認識之后:
      《Effective C++》(中文版 第3版)
      《STL源碼剖析》

    • 對操作系統,特別是Linux操作系統有一定了解之后:
      《現代操作系統》(第4版)
      《Unix環境高級編程》
      《圖解HTTP》
      《圖解TCP/IP》

    • 關于數據結構和算法:
      《數據結構》嚴蔚敏(c語言版)殷人昆(c++版)

      《漫畫算法》

    • 其他:
      《知識大遷移》

    僅為個人理解,可能有安排不合理的地方,如何選擇看自己。

  7. bug,英語的名詞,翻譯成蟲子、飛蛾等。因為第一個計算機故障由蟲子引起(指蟲子死后損壞晶體管),它便成了故障的代言詞。
    調試是debug,指排除程序的故障和不符合預期的地方。

第一個C語言程序

通過命令行運行c程序

新建一個拓展名為.txt的文件,在里面寫上c語言的程序:

#include <stdio.h>
int main()
{printf("hello bit\n");printf("he he\n");return 0;
}
//解釋:
//main函數是程序的入口
//一個工程中main函數有且僅有一個

之后將拓展名改為.c即可。.c是c語言的代碼文本文件,.cpp是c++的代碼文本文件。c++的代碼文本文件可以運行c語言的,反過來卻不行,因為c++是在c語言的基礎上進行補充。

這個程序是打印hello bit\nhe he\n在什么地方。\n是換行的意思。

安裝minGW-64,并配置環境變量。
請添加圖片描述

之后只需在cmd中將目錄切換到源碼所在的目錄,輸入命令gcc name.c -o name.exe即可生成可執行程序(在>后輸入)。運行可執行程序,輸入程序的名稱即可。

請添加圖片描述

c語言的代碼都是從main函數的第一行開始執行。一個c程序背后的源碼有且只有一個main函數。

printf是一個庫函數,即c語言的標準庫中提供的一個線程的函數,可以直接用。它的功能是在終端控制臺上打印信息。在使用printf之前一定要包含頭文件stdio.h

stdio.h是標準輸入輸出頭文件(standard,in,out三個部分組成)。關于頭文件的本質,點擊這里。

main函數還有其他的寫法。

void main(){}

古老的寫法,現在大家都不這么寫。

int main(void){}

void 表示main不接受參數,可以這樣寫。

int main(int argc, char* argv[]){}

argc:保存命令行字符串個數
argv:指針數組,每個成員都是指針(argv[0] argv[1] argv[2] …),用于成員指向命令行各字符串的首地址。

例如下面的代碼會將所有命令全部打印。

#include<stdio.h>int main(int argc,char* argv[]){int i=0;for(i=0;i<argc;i++){printf("%s\n",argv[i]);}return 0;
} 

但目前我用的編譯器都是只打印一個調用最新生成的.exe的命令。

這些操作也可以在vscode界面使用。詳細見vscode-CSDN博客。

Dev-c++5.11

Dev-c++5.11將命令行簡化成了一個或兩個按鈕。只需點擊這個按鈕即可運行。
請添加圖片描述

也可以按快捷鍵F11,Dev會自動幫我們完成輸入命令的過程。
請添加圖片描述

若出現某些語法不可用的情況,則可通過在編譯選項中添加命令修改編譯器的語言標準:
請添加圖片描述

Visual Studio系列產品

vs系列產品我更推薦vs2019和vscode。

這兩個軟件最大的特色是調試方便。現在也有很多集成開發環境(IDE)也能做到,取決于個人需求。在初學階段,社區版已經能滿足絕大多數需求。

我不喜歡用vs2022這個新版本的IDE,是因為新版本做了更加嚴密的封裝,在反匯編和特殊情況的編譯下會做出多余的行動。當然我并不是否定vs2022的功能,vs2022也有自己的特色。

vs的編輯界面,解決方案資源管理器

請添加圖片描述

在vs的安裝路徑中找到

Microsoft Visual Studio\2019\Community\Common7\IDE\VC\VCProjectItems

在其中有一個newc++file.cpp,這個是vs2019生成新的c++文件的模版。我們可以在外取一個同名的.cpp文件,之后在里面添加各種我們想要的初始語句,之后再拷貝到這個路徑進行替換即可(這個路徑可能無法修改)。

請添加圖片描述

例如我們加上一句#define _CRT_SECURE_NO_WARNINGS 1,之后在使用vs時用這個模版生成的新文件中會帶有這樣一個語句。

請添加圖片描述

生成的默認文件就會帶有這樣一句:

請添加圖片描述

請添加圖片描述

vs也可以更換

數據類型

c語言的使用方式是將現實問題轉化為能用數據和數據之間的關系模擬的抽象模型。所以學習使用c語言(甚至是其他編程語言)都繞不開用于表示數據的變量和常量。

c語言的數據類型在c++又有另外的別稱:內置類型。

char        //字符數據類型
short       //短整型
int         //整形
long        //長整型
long long   //更長的整形
float       //單精度浮點數
double      //雙精度浮點數
//C語言沒有字符串類型

案例:

#include <stdio.h>
int main()
{printf("%d\n", sizeof(char));printf("%d\n", sizeof(short));printf("%d\n", sizeof(int));printf("%d\n", sizeof(long));printf("%d\n", sizeof(long long));printf("%d\n", sizeof(float));printf("%d\n", sizeof(double));printf("%d\n", sizeof(long double));//類型的使用char ch='w';return 0;
}
  • sizeof()是一個操作符,可以返回括號內的數據占用的內存大小。

  • printf函數用于打印信息在控制臺,%d是指定打印的格式,sizeof(type)是被打印的對象。

  • char ch='w';的意思是向內存申請大小為sizeof(char)的空間來存放字符w。字符用單引號''引起來。

關于計算機存儲單位,我們知道計算機能完成這么龐大的運算,離不開底層大量的0和1的支持。

計算機只能看懂二進制,編譯器的工作就是將人寫的代碼轉變成二進制。

存放一個0或一個1所需的空間稱之為1 bit(1位)。

單位轉換:

1byte=8bit (1字節 = 8位)
1kB=2^10byte=1024byte
1MB=1024kB
1GB=1024MB
1TB=1024GB
1PB=1024TB

c語言的標準中,sizeof(long) ≥ \geq sizeof(int)long占用字節數的大小取決于編譯器的版本。

變量、常量

生活中的有些值是不變的(比如:圓周率,性別,身份證號碼,血型等等)

有些值是可變的(比如:年齡,體重,薪資)。

不變的值,C語言中用常量的概念來表示,變得值C語言中用變量來表示。

定義變量的方法

//定義變量的格式:類型 變量名=初始值;
//例如
int age=18;
//聲明變量的格式:類型 變量名;
//例如
float weight=45.10f;

對于這個語句float weight=45.10f;

若采用float weight=45.10;,系統默認45.10是double型,我們希望45.10只是float型的數據,于是在浮點數后面加后綴f

這里聲明變量最好先給他賦一個值并養成習慣,直接用沒賦值的變量,vs會出錯,Dev早期版本會產生隨機數。

變量的命名

變量的命名遵循以下規則:

  • 只能由字母(包括大寫和小寫)、數字和下劃線( _ )組成。

  • 不能以數字開頭。

  • 長度不能超過63個字符。

  • 變量名中區分大小寫的。

  • 變量名不能使用關鍵字。

其中自己再加上一條:

變量名最好有它自己的意義。

這個只是總結的,其他資料有可能有更詳細的,但遵守這個是最普適的。

變量的分類

變量按作用域分可分為全局變量局部變量。作用域暫時可以理解為離變量最近的{}

局部變量是在{}內定義的變量,全局變量是在{}之外定義的變量(狹義的理解),也可以理解為在函數外定義的變量。

#include <stdio.h>
int global = 2019;//全局變量
int main()
{int local = 2018;//局部變量//下面定義的global會不會有問題?int global = 2020;//局部變量printf("global = %d\n", global);return 0;
}

上面的局部變量global變量的定義其實沒有什么問題的。

局部變量和全局變量同名的時候,局部變量優先使用。但不可以將兩個同一作用域的變量設置為同一個名字,會產生重名的錯誤。

變量的使用

變量可以當成一個存儲數據的容器使用。包括修改、利用變量存儲的數據。

#include <stdio.h>
int main()
{int num1 = 0;int num2 = 0;int sum = 0;printf("輸入兩個操作數:>");scanf("%d %d", &num1, &num2);sum = num1 + num2;printf("sum = %d\n", sum);return 0;
}

變量的作用域和生命周期

作用域

作用域(scope)是程序設計概念,通常來說,一段程序代碼中所用到的名字并不總是有效/可用的而限定這個名字的可用性的代碼范圍就是這個名字的作用域。

總結以下就是:一個變量,哪里可以用,哪里就是它的作用域

  1. 局部變量的作用域是變量所在的局部范圍。(即自己所在的{}內部)

  2. 全局變量的作用域是整個工程。

例如:

#include<stdio>int main(){int a=1;{int b=2;printf("%d\n",b);}printf("%d\n",b);//b不在作用域,不可用return 0;
}

生命周期

變量的生命周期指的是變量的創建到變量的銷毀之間的時間段。(比如c程序的生命周期指的是程創建到銷毀的時間段)

  1. 局部變量的生命周期是:進入作用域生命周期開始,出作用域生命周期結束。

  2. 全局變量的生命周期是:整個程序的生命周期。

一個程序的生命周期與main函數是一樣的,而全局變量與main函數也是一樣的。

常量

常量即不可修改的量。c語言中的常量和變量的定義的形式有所差異。

c語言中的常量分為以下以下幾種:

  • 字面常量。例如int a=10;中的10。

  • const 修飾的常變量。例如const int a=10;中的aa本質上是一個變量,但具有了常屬性不可以被改變。)。

  • #define 定義的標識符常量

  • 枚舉常量

    枚舉,就是一一列舉所有可能性,生活中很多東西如性別、血型等情況有限可能。

#include <stdio.h>
//舉例
enum Sex
{MALE,FEMALE,SECRET
};
//括號中的MALE,FEMALE,SECRET是枚舉常量
int main()
{//字面常量演示3.14;//字面常量1000;//字面常量//const 修飾的常變量const float pai = 3.14f;   //這里的pai是const修飾的常變量pai = 5.14;//是不能直接修改的!//#define的標識符常量 演示
#define MAX 100printf("max = %d\n", MAX);//枚舉常量演示printf("%d\n", MALE);printf("%d\n", FEMALE);printf("%d\n", SECRET);//注:枚舉常量的默認是從0開始,依次向下遞增1的return 0;
}

上面例子上的 pai 被稱為 const 修飾的常變量, const 修飾的常變量在c語言中只是在語法層面限制了變量 pai 不能直接被改變,但是 pai 本質上還是一個變量的,所以叫常變量。

const int a=10;,a不可用于定義數組,即int arr[a];int arr[a]={0}不允許。

但總有特例。

在C99標準中引入變長數組的概念,可以使用變量來聲明(但不能定義)。

典型的編譯器如Dev-C++ 5.11的gcc支持。

大部分網站的OJ題支持c99。

最后,變長數組不能初始化。

操作符簡單介紹

有了變量之后,還需要有某種操作來溝通部分或全部的變量,使得變量能真正用于解決問題。例如ab代表兩個數字,想用它們解決四則運算,則需要有四則運算符。

因此c語言提供了操作符。在有的資料上,操作符又稱為運算符。

算術操作符:用于數學計算的操作符。兩邊都要有變量、常量或表達式(變量和操作符組成的集合)。

  • +:加法。
  • - :減法。
  • * :乘法。
  • /:除法得到的是商,整型會自動舍棄小數部分,浮點型按精度返回。
  • %:取模(求余數),兩個不能是整型,模正負與%前的正負相同。

樣例解析:

void f(){float a = 10/3;//等式右邊都是整數,a為3.000000float b = 10.0f/3;//或float b = 10/3.0f;
}

形如10.0f,這種是單精度浮點數表示法。我們希望用float存儲10.010.0默認為double型。double型的值賦值給float型變量,在vs中會報警告。

賦值操作符,用于修改變量。

  • =:將右邊的值賦值給左邊的變量。例如int a; a=3;只要不是跟在類型后面用于初始化,都是用于給變量賦值。
  • +=:例如:a+=2;等價于a=a+2;。下同。
  • -=*=/=%=

單目操作符,只和一個操作數(可以是變量,也可以是變量和操作符組成的表示一個值的集合)組合的操作符。

  • &:取地址(詳見指針)。
  • sizeof:返回操作數的類型長度(以字節為單位)。例如sizeof(int)就是返回int型變量在計算機中占用的空間的大小。
  • --:分前置和后置。本質是變量=變量-1的縮寫,但因前置、后置有不同的執行順序,前置是優先執行操作數再執行其他部分,后置則是優先執行其他部分再執行操作數。
  • ++:和--同理。本質是變量=變量+1的縮寫。
  • *:間接訪問操作符(解引用操作符,和指針有關)。
  • (類型):強制類型轉換。例如:(char)65=='A')

關系操作符:用于數學意義上的比較操作符。靠返回真和假來判斷。

>
>=
<
<=
!=   用于測試“不相等”
==      用于測試“相等”

邏輯操作符:用于組合

&&     邏輯與
||     邏輯或

條件操作符(三目操作符)

exp1 ? exp2 : exp3
/*
等價于
if(exp1)exp2;
elseexp3;
*/

逗號表達式:從左到右依次計算,返回最后一個表達式expn的值。

exp1, exp2, ...,expn;

下標引用函數調用結構成員訪問

  • []:用于表示數組的索引(或下標)。
  • ():有兩個含義:1、(表達式)表示這個表達式(暫時理解為語句的一部分)最先執行。2、子程序名(參數清單)表示執行某個子程序(總的程序的一部分。見函數)。
  • .:用于結構體的成員調用(見下方結構體)。
  • ->:用于結構體指針的結構體的成員的調用。

其他的操作符有的都是涉及二進制,放在另一篇詳細解釋。

語句

變量和操作符進行組合,便完成了一個功能,需要用;結尾,這個用;結尾的代碼就是語句。

c語言的代碼由語句函數(子程序)組成,而函數的主干部分是語句。這些語句分成普通語句選擇語句循環語句。普通語句就是以;結尾的語句。

選擇語句

if后面的括號內的表達式如果判斷為,則執行if后面的{}內的語句(或{}以及內部語句的代碼塊),為假則不執行

if沒有{},則if會自動匹配離它最近的語句

而且if還能和else if以及else組成多分支。

#include <stdio.h>
int main() {int coding = 0;printf("你會去敲代碼嗎?(選擇0 or 1 or 2):>");scanf("%d", &coding);//單分支if (coding == 2) {//匹配后面的{}printf("三天打魚兩天曬網,啥也不能做,只能\n");}//2個分支if (coding == 1)//匹配最近的語句printf("堅持,你會有好offer\n");else{printf("放棄,回家賣紅薯\n");}//3個及以上的分支printf("如果再來一次,你會去敲代碼嗎?(選擇0 or 1 or 2):>");scanf("%d", &coding);if (coding == 2) {//匹配后面的{}printf("三天打魚兩天曬網,啥也不能做\n");}else if (coding == 1)//匹配最近的語句printf("堅持,你會有好offer\n");else {printf("放棄,回家賣紅薯\n");}return 0;
}

循環語句

有一部分功能,需要執行很多次,同樣地拷貝粘貼會增加代碼長度。因此就有了循環語句:通過滿足某種條件執行特定的語句或代碼塊

c語言實現循環的方式有4種:

  • while
  • for
  • do {} while
  • goto

這里只介紹while,詳見循環。

while只要滿足后面括號內的語句的返回值為真,后面的語句塊會一直執行。

#include <stdio.h>
int main()
{int line = 0;while(line<=20000){line++;printf("我要繼續努力敲代碼\n");}if(line>20000)printf("好offer\n");return 0;
}

數組

既然有了變量,又會有新的問題:有的問題需要大量的變量,這時重復的拷貝粘貼會使代碼變得特別長。

c語言中給了數組的定義:一組相同類型元素(變量)的集合。

數組定義

int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定義一個整形數組,最多放10個元素

數組的下標

C語言規定:數組的每個元素都有一個下標,下標是從0開始的。

數組可以通過下標來訪問的。

比如:

int arr[10] = {0};
//如果數組10個元素,下標的范圍是0-9

請添加圖片描述

數組簡單使用

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

printf("%d ", arr[i]);的解釋:

arr[i]是用于訪問下標為i的元素(下標訪問操作符[]),將arri結合在一起,讓我們訪問arr[i]存放的元素。

所以arr和數組中的內容4[]這個操作符的操作數。

變長數組的概念

C99標準之前,數組的大小只能是常量指定。例如:

int a[10];

即使用#define定義符號,在編譯階段也會全部替換回來,本質還是只能常量指定。

在C99標準中,引入一個變長數組的概念。變長數組允許數組的大小使用變量來指定,例如:

void f(){int n = 10;int a[n];
}

大部分網站的OJ題都支持C99。

此外,變長數組不能初始化。也就是說不允許這種寫法:

int a[n]={0};

字符串和轉義字符

字符串

"Hello, world!\n"這種由雙引號(Double Quote)引起來的一串字符稱為字符串字面值(String Literal),或者簡稱字符串。c語言表示字符用單引號。例如:'a''2'

字符串是最后一個元素為\0char型數組。

注:字符串的結束標志是一個\0的轉義字符,ASCII值為0。在計算字符串長度的時候\0是結束標志,不算作字符串內容。

#include <stdio.h>
//下面代碼,打印結果是什么?為什么?(突出'\0'的重要性)
int main()
{char arr1[] = "bit";//字符串里隱藏一個'\0'char arr2[] = {'b', 'i', 't'};//無'\0',只是將三個字符放進去char arr3[] = {'b', 'i', 't''\0'};printf("%s\n", arr1);printf("%s\n", arr2);printf("%s\n", arr3);return 0;
}

打印結果(不同的設備情況可能不同):

bit
bit燙燙燙燙蘠it
bit

分析:

char arr1[] = "bit";內部結構:

請添加圖片描述

char arr2[] = {'b', 'i', 't'};的結尾并不是\0,也就不是字符串。

printf("%s\n", arr1);%s的格式是打印字符串,直到檢測到'\0'結束。因arr2內無'\0',系統找不到'\0',則繼續訪問內存直到找到\0為止。而這個數組存放在內存中,前后都有空間,所以避免不了訪問不屬于自己的空間。

打印燙的原因:燙字的GBK編碼正好都是0xcc

請添加圖片描述

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>int main()
{char arr4[] = { "燙" };char arr5[] = { "燼" };int i = 0;for (i = 0; i < 2; i++) {printf("%x ", arr4[i]);//十六進制打印}printf("\n");for (i = 0; i < 2; i++) {printf("%x ", arr5[i]);}return 0;
}

p.s. 函數strlen返回值為size_t( #define unsigned int size_t ),但它依舊是以\0為結束標志。所以strlen(arr2)的返回值是隨機的(統計\0之前的字符數)。

即使printf("%d",strlen(arr2));成功輸出,結果也無代表性。

轉義字符

轉義,即轉變意思的意思。

案例:

#include <stdio.h>
int main()
{printf("c:\code\test.c\n");return 0;
}

輸出:

請添加圖片描述

這里就不得不提一下轉義字符了。轉義字符顧名思義就是轉變意思。

下面看一些可能比較常用的轉義字符。

\?

在書寫連續多個問號時使用,防止他們被解析成三字母詞。

比如:??]就是],在早期的一些編譯器會將??]解釋成三字母詞并轉變成其他符號。

\'

用于表示字符常量'

\"

用于表示一個字符串內部的雙引號

\\

用于表示一個反斜杠,防止它被解釋為一個轉義序列符。

\a

警告字符,蜂鳴

\b

退格符。

例如。

#include <stdio.h>
int main()
{int i=0;printf("ab\b");scanf("%d",&i);printf("\n");printf("ab\bc");return 0;
}

第5行輸出ab,但光標夾在a、b中間,輸入任意數字都會將b給覆蓋。

第8行先輸出ab,后經過\b退格,使光標夾在a、b中間,再輸出c就會將b給覆蓋掉。

\f

進紙符

\n

換行

\r

回車。感覺上更像Tab鍵,推進2~4個字節(空格)的空間。

\t

水平制表符

\v

垂直制表符

\ddd

ddd表示1~3個八進制的數字。 如: \130表示X。

13 0 ( 8 ) = 1 × 8 2 + 3 × 8 1 + 0 = 8 8 ( 10 ) 130_{(8)}=1\times8^2+3\times8^1+0=88_{(10)} 130(8)?=1×82+3×81+0=88(10)?,ASCII碼值可知這個符號是X

在計算機中的字符被解釋成十進制(詳見下方的ASCII碼表),每個字符規定一個值。

請添加圖片描述

其中\777轉換成十進制數則大于127(即ASCII碼的最大碼值),對字符來說太大,vs會警告。

\xdd

dd表示2個十六進制數字。 如: \x30是字符0

在了解這些轉義字符后,再來看這個代碼:

#include <stdio.h>
int main()
{//在屏幕上打印一個單引號'printf("%c\n", '\'');//在屏幕上打印一個字符串,字符串的內容是一個雙引號“printf("%s\n", "\"");return 0;
}

若第5行這樣寫:printf("%c\n", ''');,編譯器會將前兩個'解釋成一對,從而使后面的'落單,這樣一來編譯器反而不能識別這個代碼。

三個0的區別:

0: 數字0

'0':字符0,ASCII值為48。

'\0':字符,ASCII值是0。

注釋

  1. 代碼中有不需要的代碼可以直接刪除,也可以注釋掉。

  2. 代碼中有些代碼比較難懂,可以加一下注釋文字。

可以理解為注釋是寫給程序員看的,編譯器在預編譯階段會將注釋刪除。

注釋有兩種風格:

  • c語言風格的注釋/*xxxxxx*/

缺陷:不能嵌套注釋。

例如,

/*1
/*
*/2
*/3

1和2進行匹配,使得3暴露在外。

  • C++風格的注釋//xxxxxxxx

    • 一次只能注釋一行。

函數

同樣是代碼塊執行多次,但不能每次都寫循環,這樣會增加代碼的長度,于是就有了函數。

因此函數的作用是代碼復寫(或者說重復利用)。

#include <stdio.h>
int main()
{int num1 = 0;int num2 = 0;int sum = 0;printf("輸入兩個操作數:>");scanf("%d %d", &num1, &num2);sum = num1 + num2;printf("sum = %d\n", sum);return 0;
}

上述代碼,寫成函數如下:

#include <stdio.h>
int Add(int x, int y)
{int z = x + y;return z;
}
int main()
{int num1 = 0;int num2 = 0;int sum = 0;printf("輸入兩個操作數:>");scanf("%d %d", &num1, &num2);sum = Add(num1, num2);printf("sum = %d\n", sum);return 0;
}

關于scanf的返回值

例如:

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

scanf是從鍵盤上獲取數據到變量空間中,若輸入成功,則scanf返回成功填充的字符個數。

所以scanf將讀到的數據賦值給a后返回1;給ab返回2,即c的值為1或2。

所以scanf的返回值為讀到的數據個數。若讀取失敗則返回EOF也就是-1。

stdio.h給出的定義是

#define EOF (-1)

EOF:end of file,用于文件結束的標志。

scanf讀取失敗,在控制臺輸入Ctrl+z即可。部分編譯器比如vs可能需要多輸入幾次。

常見關鍵字

c語言提供了豐富的關鍵字,這些關鍵字都是語言本身預先設定好的,用戶自己是不能創造關鍵字的。

我的打算是學習時遇到一個關鍵字就做總結,在學完c語言的大部分核心內容之后,再出一篇c語言的關鍵字的總篇集,方便查詢。

c語言的關鍵字:

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

#define 定義常量和宏

在一篇文章看懂c語言-CSDN博客已經提到#define的作用。這里再介紹一個和函數的功能十分類似的功能,也就是宏。

例如:

//define定義標識符常量
#define MAX 1000
//define定義宏
#define ADD(x, y) ((x)+(y))
int main()
{int sum = ADD(2, 3);sum = 10 * ADD(2, 3);return 0;
}

將這個代碼在控制臺通過gcc進行預編譯即可得到如下結果:

請添加圖片描述

#include#define這種#開頭的符號稱預處理指令,它不是關鍵字。

關于宏:宏雖然在使用上和函數類似都是代碼重用,但畢竟是符號替換,在程序源碼編寫上存在區別。

宏的不標準寫法:#define ADD(x, y) (x+y)。將參數用()括起來可以更準確,防止因為優先級與其他符號產生沖突。

指針

通過指針可以理解變量是如何在內存中存在的。

內存

內存是電腦上特別重要的存儲器,計算機中程序的運行都是在內存中進行的 。

所以為了有效的使用內存,就把內存劃分成一個個小的內存單元,每個內存單元的大小是1個字節。

為了能夠有效的訪問到內存的每個單元,就給內存單元進行了編號,這些編號被稱為該內存單元的地址。這種地址在c/c++中又把他稱作指針

為啥不分到最小單位bit?若這樣分配,則相當于指定到某房間的第幾平米處處理數據(太細不好處理),1個char類型的變量1個字節,再細的話不合理。

很多時候32位的二進制序列太長,我們將他們用十六進制表示。

請添加圖片描述

每個內存單元都有自己的編號,編號稱做地址,地址又稱作指針。

所以編號、地址、指針三個說法是一回事。

地址的產生(可跳過)

當我們在32位機器上,有32根地址線(有物質形態的電線),該電線是通電的,通電后有高、低電平,高、低電平轉換成數字信號就是高電平為1和低電平為0(也可以反邏輯即高電平為0和低電平為1)。

這種32位機器表示的32位二進制數能代表 2 32 2^{32} 232種電信號,此時32根電線產生的電信號,轉換成數字信號的二進制序列可作為內存編號,通過內存編號可找到對應的內存空間。

所以內存分為一個個內存單元,每個內存單元都對應一個編號,編號由硬件電路產生。

請添加圖片描述

一個內存單元是1個字節,這種內存單元可以給出一個地址。能產生 2 32 2^{32} 232個地址(或 2 32 2^{32} 232個二進制序列),即一個32位機器用于記錄地址的數據有 2 32 2^{32} 232個,它們能夠管理2^{32}byte的空間。

2 32 2^{32} 232byte = 4 =4 =4GB。

在vs界面可發現x86處有一個配置管理器,通過更改配置管理平臺,指針變量的地址存儲空間會發生變化。

一般 X86 對應 32位(bit),X64 對應 64位(bit)。

變量的地址

#include <stdio.h>
int main()
{int num = 10;&num;//取出num的地址//注:這里num的4個字節,每個字節都有地址,//取出的是第一個字節的地址(較小的地址)printf("%p\n", &num);//打印地址,%p是以地址的形式打印return 0;return 0;
}

請添加圖片描述

&num實際占用4byte的空間(X64下是8byte),每個byte都有自己的地址,&num只是取出第1個byte空間的地址。

取出的地址也是十六進制數,也需要內存空間存儲,通常用

type* name = &num;

來存儲。我們把name稱指針變量(存放地址也就是指針的變量),name的類型是type*

*說明name是指針變量,type說明name指向的對象是type類型。*跟隨變量還是類型沒有具體要求。

指針的使用實例:

#include <stdio.h>
int main()
{int num = 10;int* p = &num;*p = 20;return 0;
}

&num:獲得num的地址。&是取地址操作符。

*p*是解引用操作符,解引用是p里存地址,*p就是解引用,它是通過p里的地址找到這個地址指向的變量,對那個變量的存儲的數據進行操作。

結構體

結構體是一些具有某種聯系的變量、數組等的集合體。盡管不用結構體,將變量單獨列出來通過運算也能展示關系。

比如描述學生,學生包含: 名字+年齡+性別+學號 這幾項信息。

就可以用結構體來描述。

struct Stu
{char name[20];//名字int age;//年齡char sex[5];//性別char id[15];//學號
};

復雜類型生成的復雜對象(類似數據類型生成的變量)不能使用單個內置類型來描述。

內置類型即c語言本身就具有的,比如:charshortintlonglong longfloatdouble

struct是自定義類型,并不屬于內置類型。

結構體的簡單應用:

#include <stdio.h>
struct Stu {char name[20];//名字int age;//年齡char sex[5];//性別char id[15];//學號
};
int main() {//結構體變量的初始化struct Stu s = { "張三",20, "男", "20180101" };//.為結構成員訪問操作符printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id);//->操作符,用于指針變量struct Stu* ps = &s;printf("name = %s age = %d sex = %s id = %s\n", (*ps).name, ps->age, ps->sex, ps -> id);return 0;
}

ps->name可用(*ps).name代替。即先找到對象,再訪問成員。

通常引用成員:

結構體變量.成員

結構體指針->成員

看到這里,對c語言相比有了一個大概的框架。后面都是對某一類知識點做更詳細的介紹。全篇下來整合成一篇完全適合小白的書籍完全可以。

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

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

相關文章

Nginx核心功能及正則表達

目錄 一&#xff1a;正向代理 1&#xff1a;編譯安裝nginx &#xff08;1&#xff09;安裝支持軟件 &#xff08;2&#xff09;創建運行用戶、組和日志目錄 &#xff08;3&#xff09;編譯安裝nginx &#xff08;4&#xff09;添加nginx系統服務 2&#xff1a;配置正向代…

npm命令介紹(Node Package Manager)(Node包管理器)

文章目錄 npm命令全解析簡介基礎命令安裝npm&#xff08;npm -v檢插版本&#xff09;初始化項目&#xff08;npm init&#xff09;安裝依賴包&#xff08;npm install xxx、npm i xxx&#xff09;卸載依賴包&#xff08;npm uninstall xxx 或 npm uni xxx、npm remove xxx&…

【Linux】Linux基礎概念

一些比較重要的使用Linux的前情提要。 部分經驗來源于網絡&#xff0c;若有侵權請聯系我刪除&#xff0c;主要是做筆記的時候忘記寫來源了&#xff0c;做完筆記很久才寫博客。 專欄目錄&#xff1a;記錄自己的嵌入式學習之路-CSDN博客 目錄 1 Shell命令參數 2 系統變量…

阿里開源Qwen3:大語言模型的新突破

一、模型概覽&#xff1a;豐富的模型家族 Qwen3 系列包含了 2 款混合專家&#xff08;MoE&#xff09;模型與 6 款密集&#xff08;Dense&#xff09;模型&#xff0c;參數量覆蓋范圍極廣&#xff0c;從 0.6B 一直延伸至 235B 。其中&#xff0c;旗艦模型 Qwen3 - 235B - A22B…

數字智慧方案5856丨智慧環保綜合解決方案(50頁PPT)(文末有下載方式)

資料解讀&#xff1a;智慧環保綜合解決方案 詳細資料請看本解讀文章的最后內容。 隨著城市化進程的加速和環境問題的日益嚴峻&#xff0c;智慧環保成為提升城市環境管理水平的重要手段。本文將對智慧環保綜合解決方案進行詳細解讀&#xff0c;探討其在實際應用中的需求、解決…

基于ssm的網盤管理系統(全套)

一、系統架構 前端&#xff1a;vue | element-ui 后端&#xff1a;spring | springmvc | mybatis 環境&#xff1a;jdk1.8 | mysql | maven | tomcat | nodejs 二、代碼及數據庫 三、功能介紹 01. 注冊 02. 登錄 03. 管理員-首頁 04. 管理員-個人中心 …

PostgreSQL 的 VACUUM 與 VACUUM FULL 詳解

PostgreSQL 的 VACUUM 與 VACUUM FULL 詳解 一、基本概念對比 特性VACUUMVACUUM FULL定義常規維護操作&#xff0c;清理死元組激進重組操作&#xff0c;完全重寫表數據鎖級別不阻塞讀寫(共享鎖)排他鎖(阻塞所有操作)空間回收只標記空間為可用&#xff0c;不返還OS空間返還操作…

復刻低成本機械臂 SO-ARM100 舵機配置篇(WSL)

視頻講解&#xff1a; 復刻低成本機械臂 SO-ARM100 舵機配置篇&#xff08;WSL&#xff09; 飛特舵機 組裝之前需要配置舵機的ID&#xff0c;如下的網址為舵機的資料&#xff0c;實際上用不到&#xff0c;但可以mark在這里 Software-深圳飛特模型有限公司 User Guide里面可以…

Tailwind CSS實戰技巧:從核心類到高效開發

使用 Kooboo平臺 訓練實戰技巧&#xff0c;無需配置安裝&#xff0c;直接引入CDN就可以在線練習了&#xff01;具體操作流程&#xff1a;進入Kooboo后&#xff0c;選擇創建空白站點 -> 站點開發 -> 控制面板 -> 頁面 ->新建普通頁面 -> 編寫代碼 一、核心布局類…

【LINUX操作系統】線程操作

了解了線程的基本原理之后&#xff0c;我們來學習線程在C語言官方庫中的寫法與用法。 1. 常見pthread接口及其背后邏輯 1.1 pthread_create 與線程有關的函數構成了?個完整的系列&#xff0c;絕?多數函數的名字都是以“pthread_”打頭的 ? 要使?這些函數庫&#xff0c;…

【AI面試準備】Azure DevOps沙箱實驗全流程詳解

介紹動手實驗&#xff1a;通過 Azure DevOps 沙箱環境實操&#xff0c;體驗從代碼提交到測試篩選的全流程。如何快速掌握&#xff0c;以及在實際工作中如何運用。 通過 Azure DevOps 沙箱環境進行動手實驗&#xff0c;是快速掌握 DevOps 全流程&#xff08;從代碼提交到測試篩選…

VulnHub-DC-2靶機

主機發現 sudo arp-scan -l 以sudo管理員權限掃描本地活動ip地址 Interface: eth0, type: EN10MB, MAC: 08:00:27:22:46:4f, IPv4: 192.168.252.230 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.252.6 4c:5f:70:74:3c:3b …

藏語英語中文機器翻譯入門實踐

&#x1f3af; 項目目標&#xff1a; 輸入藏文句子&#xff0c;自動翻譯成英文和中文&#xff08;或輸入中文&#xff0c;翻譯為英文和藏文&#xff09;。 &#x1f50d; 技術與原理簡介 機器翻譯&#xff08;Machine Translation, MT&#xff09;是人工智能中自然語言處理&a…

【阿里云大模型高級工程師ACP習題集】2.9 大模型應用生產實踐(上篇)

練習題 【單選題】在自然語言處理的法務咨詢場景中,以下哪種模型選擇最為合適? A. 通用大語言模型 B. 經過數學領域微調的模型 C. 面向法律領域訓練的模型 D. 視覺模型 【多選題】以下哪些屬于模型非功能性需求?( ) A. 模型對不同語言的支持能力 B. 模型的響應速度要求 C.…

WPF之ProgressBar控件詳解

文章目錄 1. ProgressBar控件簡介2. ProgressBar的基本屬性和用法2.1 基本屬性2.2 基本用法2.3 代碼中修改進度 3. 確定與不確定模式3.1 確定模式&#xff08;Determinate&#xff09;3.2 不確定模式&#xff08;Indeterminate&#xff09; 4. 在多線程環境中更新ProgressBar4.…

IntelliJ IDEA 保姆級安裝教程(附安裝包)

文章目錄 一、下載二、安裝三、啟動 一、下載 Ultimate 2021.1.1 - Windows x64 (exe) 二、安裝 三、啟動 首次安裝啟動 非首次安裝啟動

Performance API 性能上報

以下是關于 Performance API 性能上報的基本知識點總結: 一、性能監控核心指標體系 1. 關鍵性能指標(Web Vitals) 指標標準采集方式健康閾值LCP (最大內容繪制)測量加載性能PerformanceObserver≤2.5sFID (首次輸入延遲)測量交互響應PerformanceObserver≤100msCLS (累積布…

C語言-指針(一)

目錄 指針 內存 概念 指針變量 取地址操作符&#xff08;&&#xff09; 操作符“ * ” 指針變量的大小 注意 指針類型的意義 作用 void * 指針 const修飾指針變量 const放在*前 const放在*后 雙重const修飾 指針的運算 1.指針 - 整數 2.指針 - 指針 3.指…

華為云Astro大屏連接器創建操作實例:抽取物聯網iotda影子設備數據的連接器創建

目錄 樣圖(API連接器創建成功) 說明 操作場景(以Astro大屏抽取iotda影子參數為例) 實際操作步驟 新建連接器 設置基本信息。 接口鑒權方式,支持API鑒權、AK/SK、API Key和無身份驗證 無身份驗證 AK/SK認證(目前暫不能用) API Key認證(第三方使用) API鑒權認…

【硬件系統架構】哈佛架構

一、引言 在計算機科學的浩瀚宇宙中&#xff0c;計算機體系結構猶如星辰般繁多且各有獨特光芒。哈佛架構便是其中一顆耀眼的明星&#xff0c;它在眾多計算機體系結構中占據著獨特而重要的地位。從計算機技術的萌芽期一路走來&#xff0c;哈佛架構不斷發展演變&#xff0c;在不同…