日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言重难点

發布時間:2024/1/8 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言重难点 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C語言

編譯過程

GCC概述

GCC最初的全名是GNU C Compiler
隨著GCC支持的語言越來越多,它的名稱變成了GNU Compiler Collection
翻譯官 翻譯組織

文件后綴名 gcc
.c

gcc -o output
gcc -o 輸出的文件名 輸入文件名

gcc -v -o

c語言的編譯過程

預處理—編譯—匯編—鏈接

預處理: .I 文件 替換過程,沒有include define等

編譯: 匯編文件 .s

匯編: 生成目標文件 .o

鏈接: 鏈接資源 build

gcc的語法所對應的內容

預處理:cpp -o a.i 001.c 【gcc -E】
編譯 :/usr/lib/gcc/i486-linux-gnu/4.4.3/cc1 -o a.s 001.c 【gcc -S】
匯編:as -o a.o a.s 【gcc -c】
鏈接:/usr/lib/gcc/i486-linux-gnu/4.4.3/collect2 -o build a.o+… 【gcc -o】 gcc -o build 001.c
【問題】
define include是關鍵字嗎? 是預處理命令

預處理

Include

< > 尖括號是系統中的

" "是自定義的

#include 包含頭文件

#define 宏 替換 不進行語法檢查

#ifdef #else #endif 條件預處理

#include <stdio> #define ABC int main(){#ifdef ABCprintf("=====%s=====",——FILE__);#endifprintf("hello world\n“)return 0; }

發行版本不希望別人看到自己的代碼結構,可以設置#ifdef #else#endif ,來調節是否打印。

gcc -DABC == #define ABC

預定義宏(兩個下劃線)

_FUNCTION_ :函數名

_LINE_: 行號

_FILE_ : 文件名

宏體# ## 區別:

# 字符串化

## 連接符號

#include <stdio> #define ABC(x) #x #define DAY(x) myday##xint main() {int myday1 = 10;int myday2 = 20;printf(ABC(ab\n));printf("the day is %d\n",DAY(1));return 0; }

結果:

ab

10

DAY(1)調用的是myday1,通過#連接myday

關鍵字

數據類型

硬件芯片操作的最小單位:
bit 1 0
軟件操作的最小單位: 8bit == 1B

網速之間的轉換:

? 4M 4Mbit Kbit/s KB/S

char

硬件芯片操作的最小單位: bit

軟件操作的最小單位: char

8bit = 1B

硬件處理的最小的單位: char

最大的是256

int

大小: 根據編譯器來決定。

編譯器最優的處理大小:

系統一個周期,所能接受的最大處理單位 int

32bit的系統,4B 恰好能接收int類型

16bit的系統 , 2B int

300L 后面的L表示long類型的,可以表示一個很大的數,

long short

特殊長度

unsigned、signed

無符號:數據

有符號:數字

區別:內存空間的最高字節是符號位還是數據

float、double

浮點數

float 代表 4B

double代表 8B

浮點型常量

1.0f 是float類型

1.1 是double 的類型

void

一般是聲明標志,不是使用標志

void fun() 表示函數不反悔。

自定義數據類型

C編譯器默認定義的內存分配不符合實際資源的形式(例如定義寄存器的大小)

struct 、union、enum、typedef

struct

元素之間的和

struct myabc{unsigned int a;unsigned int b;unsigned int c; }; struct myabc mybuf;

結構體最后加分號,abc的順序不同,可能結構的大小也不相同(涉及字節對齊的問題)

union

共用起始地址的一段內存(共用體

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-o8qu2Rvm-1606119305231)(file:///C:/Users/15890/AppData/Local/Packages/Microsoft.Office.OneNote_8wekyb3d8bbwe/TempState/msohtmlclip/clip_image001.png)]

定義b,a可能發生改變。

enum

enumerate 一一列舉

被命名的整型常數的集合

#define MON 0 #define TUE 1 #define WED 2 /* 上述的宏可以表示為 */ enum abc{ MOD = 0,TUE,WED }

enum 枚舉名稱{ 常量列表 };

#include <stdio.h>enum week{ Monday = 0 ,Tuesday =1 ,Wednesday = 2,Thursday,Friday,Saturday,Sunday }; int main() {enum weel a1; /* 定義了這樣的空間 */printf("the a1 is %lu\n",sizeof(a1));printf ("the %d\n",WED);return 0; }

運行結果:

4

2

枚舉變量就是個整數,只是這個整數可以取這集合面所有的值

enum DAY{}day;定義枚舉類型同時定義枚舉變量;

enum {}day; 可以省略名稱,直接定義枚舉變量;

typedef

數據類型的別名

typedef int a_t; /* a是一個int類型的外號 */ a_t mysize;

雜項

Sizeof

它是關鍵字

編譯器給我們查看內存空間容量的一個工具

return

:返回函數

邏輯結構

cpu是順序執行程序

PC 指針分支 --> 選擇

代碼周期性的循環,節約內存。

條件選擇

if else 、switch、case、default、

循環

do、while(條件)、for(次數)、

循環中的控制符

continue、break、goto(在同一個函數中可以跳)

switch(整形數)

{case 整形數i:

}

類型修飾符

對內存資源存放位置的限定

auto、register、static、const、extern、volatile

有的可讀可寫,有的可讀,有的可寫

Auto

可讀可寫的內存空間 默認平時就是 auto char a;如果放入大括號里,就是存放在棧里;

register

register int a;限定變量定義在寄存器上的修飾符; 寄存器速度快,內存上面慢

編譯器會盡量的安排CPU的寄存器取存放這個a,如果寄存器不足,a還是放在存儲器中。

**&**這個符號對register不起作用;

內存(存儲器) 寄存器

0x100 R0,R2

static

靜態變量

**修飾3種數據:**函數內部的變量;函數外部的變量;函數的修飾符;

修飾3種數據:
1)、函數內部的變量

int fun(){ int a; ==> static int a;}

2)、函數外部的變量

int a; ==> static int a; int fun() {}

3)、函數的修飾符

int fun(); ==> static int fun();

const

常量定義、只讀的變量,不能修改

可以通過指針的技巧去修改

extern

外部申明;也是再全局變量中使用;

volatile

告知編譯器編譯不優化

修飾變量的值的修改,不僅僅可以通過軟件,也可以通過其他方式(硬件外部的用戶)

int a = 100;while( a==100 );mylcd();

[a] 表示 a 的地址

f1: LDR R0,[a] f2: CMP R0,#100 f3: JMPeq f1 ----> JMPEQ f2 f4: mylcd();

修飾變量的值的修改,不僅僅通過軟件,也可以通過其他方式。例如: 如果外界接了鍵盤來鍵入a,則就會發生錯誤;

運算符

算術運算符

+、-、*、/、%

* 、/ 大部分是不支持的。

CPU可以在一個周期處理+ ,但是 * 在一個周期處理不了,需要利用軟件進行模擬實現乘法

% 取模,4%3 = 1; 1%3=1;

應用場景:

  • 任意一個N,我們模上M過后,得到M進制的個位數;

  • 取一個范圍的數;

    ? eg:給一個任意的數,得到一個1到100以內的數:(m%100)+1

  • 循環數據結構的下標。

  • 邏輯運算

    真與假 返回結果為 1 和 0

    || 、 & 、

    A || B ≠ \neq ?= B || A 不相等

    #include <stdio.h> int main() {int a =10;int res;res = ((a==10) || printf("======\n"));printf("the res is %d\n",res);return 0; }

    結果:1

    a若足,則不看式子后面的內容了,若把a != 10,則會輸出 ====

    < 、>= 、 <= 、 >、!、? :

    位運算

    << 、 >>

    左移 : 乘法 *2 二進制下的移位
    m << 1; m × 2 \times2 ×2
    m << n m × 2 n \times2^n ×2n

    4: 0 0 1 0 0 8: 0 1 0 0 0int a = b*32; ===> b <<5

    [數據、數字]
    -1 *2 -2:
    8bit (負數先取反,再加一)
    1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0
    1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1
    1 1 1 1 1 1 1 1 === -1 1 1 1 1 1 1 1 0 == -2

    負數也滿足

    右移:除以2
    m >> n m/2^n
    符號變量有關 有符號數整數填1,無符號數填0.

    int a; a>>n unsigned int a a>>n int a = xxx; while(a){a = a>>1; } printf("-------------\n");

    如果a為負數,永遠也不會為0;

    如果a為正數,可以為0;

    & 、 |

    A & 0 ----> 0
    &: 屏蔽
    int a = 0x1234;
    a & 0xff00; 屏蔽低8bit,取出高8bit

    &:取出

    A & 1 —> A

    &:清零器 clr

    |
    A | 0 = A
    保留
    A | 1 = 1
    設置為高電平的方法,設置set

    設置一個資源的bit5為高電平,其他位不變
    int a;
    a = (a | (0x1<<5)); =====> a | (0x1<<n)

    清除第五位

    int a;
    a = a & 0 1 1 1 1 1 31 a & 31 31 : 32bit
    ~(0x1<<5)

    a = a & ~(0x1<<5); =====> a = a & (~(0x1<<n));

    我們想資源456bit設置為101?

    ^

    相同位為假

    a = a ^ b

    b = a ^ b

    a = a ^ b

    可以交換 a ,b的值

    內存訪問

    ( ) 限制符號

    ? 函數訪問符號

    [ ] 數組,內存訪問的 ID 符號

    { } 函數體的限制符

    –> 地址訪問

    . 變量訪問

    C語言內存空間的使用

    指針

    指針的概述

    內存類型資源地址、門牌號的代名詞
    指針變量 : 存放指針這個概念的盒子

    int a;
    int *p;
    char *p;

    C語言編譯器對指針這個特殊的概念,有2個疑問?
    1、分配一個盒子,盒子要多大?
    在32bit系統中,指針就4個字節
    2、盒子里存放的地址 所指向 內存的讀取方法是什么?

    ? 聲明,得到大小,一次讀多少字節。確定位置

    指針指向內存空間,一定要保證合法性

    浮點數在內存中表現形式很奇怪

    浮點數讀取,指針定義為unsigned,無符號類型。

    指針修飾符

    const

    常量、只讀【不能變】

    雙引號就是常量,不可改變 const char型

    內存屬性:
    1、內存操作的大小
    2、內存的變化性,可寫可讀

    char *p;

    const char *p; 【T】 字符串 “ hello world” “aaa”

    char const *p;

    指向的內容不可以變,指針可以指向其他的地址 字符串

    char * const p; 【T】 硬件資源 LCD

    char *p const;

    指向的內容可以改變,指針不能指向別的地方 硬件資源 LCD

    const char * const p ROM

    第三種,都不可以變 ROM

    volatile

    防止優化指向內存地址

    char *p;

    volatile char *p ;*p == 0x10 與之前的相同:while( *p == 0x10 );xxxx;
    typedef

    char *p;

    什么類型 變量名稱;

    xxx a;

    int (*p[10])(int ,void (*p)(int));char *name_t : name_t是一個指針,指向了一個char類型的內存 typedef char *name_t; name_t是一個指針類型的名稱,指向了一個char類型的內存name_t abc;

    指針運算符

    ++ 、–、+、-

    int a = 100;
    a+1

    int *p = xxx [0x12]

    p+1 [0x12 + 1*(sizeof(*p))]

    指針的加法、減法運算,實際上加的是一個單位,單位的大小可以使用sizeof(p[0])

    int *p p+1
    char *p p+1

    p++ p-- : 更新地址

    [ ]

    變量名[ n ]

    n:ID 標簽
    地址內容的標簽訪問方式
    取出標簽里的內存值

    操作邏輯符

    >= 、<= 、== 、 !=

    int *p1;
    int *p2;

    p1 > p2
    *p1 > *p2

    --------- == !=
    1、跟一個特殊值進行比較 0x0 : 地址的無效值,結束標志
    if( p == 0x0)
    NULL
    2、指針必須是同類型的比較才有意義
    char *
    int *

    多級指針

    int **p;

    存放地址的地址空間

    char **p;

    p[0] p[1] … p[n]

    p[m] == NULL ----> 結束了

    數組

    數組的定義

    內存的一種分配形式

    定義一個空間:
    1、大小
    2、讀取方式

    數據類型 數組名[m] m 的作用域是在申請的時候

    數組名是一個常量符號,一定不要放到=的左邊 ,舉例。

    char buf[100];

    buf = “hello world”;

    數組名不能 a++,數組名就是數組的常量標簽

    int a[100];

    越界
    a[10]

    數組空間的初始化

    空間的賦值
    按照標簽逐一處理
    int a[10]; [ 0 - 9 ]
    a[0] = xx
    a[1] = yy;

    程序員這樣賦值,工作量比較大,能不能讓編譯器進行一些自動處理,幫助程序員寫如上的程序
    ----》空間定義時,就告知編譯器的初始化情況,空間的第一次賦值,初始化操作

    int a[10] = 空間;
    C語言本身,CPU內部本身一般不支持空間和空間的拷貝
    int a[10] = {10,20,30};

    ====> a[0] = 10; a[1] = 20; a[2] = 30; a[3]=0;

    數組空間的初始化 和 變量的初始化 本質不同,尤其在嵌入式的裸機開發中,空間的初始化往往需要庫函數的輔助

    char

    char buf[10] = {‘a’,‘b’,‘c’}; 3個字節

    buf當成普通內存來看,沒有問題
    buf當成一個字符串來看,最后加上一個’\0’ 字符串的重要屬性,結尾一定有個’\0’

    char buf[10] = {"abc"}; //4個字節 char buf[10] = "abc"; //此時是**常量對變量的拷貝**,buf[2] = 'e'; //對的 char *p = "abc";p[2] = 'e'; //會出現段錯誤 char buf[] = "abcd"; //5個字節 char buf[10] = "abc"; buf = "hello world" //錯誤 數組名不應該放到等號的左邊,數組標簽不能改。

    第二次內存初始化,賦值?
    逐一處理
    buf[0] = ‘h’ buf[1] = ‘e’ … buf[n] = ‘d’, buf[n+1] = 0; (不要忘了0)

    strcpy、strncpy

    一塊空間,當成字符空間,提供了一套字符拷貝函數

    字符拷貝函數的原則:
    內存空間和內存空間的逐一賦值的功能的一個封裝體
    一旦空間中出現了0這個特殊值,函數就即將結束。

    strcpy();char buf[10] = "abc"; buf = "hello world"; //錯誤的 應該是下面這個 strcpy(buf,"hello world"); 內存泄漏函數
    非字符串空間

    字符空間
    ASCII碼編碼來解碼的空間,----》給人看
    %s abc ‘a ’ ‘b’ ’ c’
    \0作為結束標志
    非字符空間
    數據采集 0x00 - 0xff 8bit
    開辟一個存儲這些數據盒子

    ? char buf[10]; ----> string 字符
    unsigned char buf[10];----> data 數據

    buf = “abc”;
    unsigned char *p = sensor_base;
    只管逐一拷貝,結束在哪里?只能定義個數

    拷貝三要素:
    1、src
    2、dest
    3、個數

    memcpy
    int buf[10]; int sensor_buf[100];memcpy(buf,sensor_buf,10*sizeof(int));unsigned char buf1[10]; unsigned char sensor_buf[100];// 00 00 00 23 45 78 strncpy(buf,sensor_buf,10) memcpy(buf,sensor_buf,10*sizeof(unsigned char));

    指針數組

    int a[100] char * a[100]; //100個地址sizeof(a) = 100 * 4;int b; sizeof(b)char **a; //地址里面還是地址

    多維數組

    定義一個指針,指向int a[10]的首地址
    定義一個指針,指向int b[5][6]的首地址

    二維數組是一塊一塊讀的,

    int *p1 = a; int **p2 = b; //無效的指針類型int *p; int *p[5];int a; int a[5];int *p[5]; //p是5個空間,5個空間里存int* 與我們定義的一塊一塊讀是不一樣的。 int (*p)[5]; //5個int指針 和int a[5] 相似

    結構體

    字節對齊

    strcuct abc {char a; int b};

    1 + 4 = 5

    效率,希望犧牲一點空間換取時間的效率
    最終結構體的大小一定是4的倍數

    結構體里成員變量的順序不一致,也會影響到他的大小

    位域

    內存的分布圖

    int a; 默認方式

    編譯 —》匯編 —》鏈接
    *.o build

    4G的大小

    內核空間 應用程序不許訪問 (占用1G


    棧空間 局部變量 RW


    運行時的堆空間 malloc


    全局的數據空間 (初始化的,未初始化) static RW data bss

    只讀數據段 “hello world” 字符串常量 R TEXT

    代碼段 code R TEXT


    0x0 :

    局部變量;

    函數結束后就會“銷毀”失效了。

    局部的都在棧上

    全局未初始化—bss,初始化—data

    static 的變量也在全局 ,但是出了大括號就沒用了(訪問的局部變量),還是存在在全局變量的區域

    生成可執行文件,一般打包最后一個段中的內容。 text在代碼段會代入build文件中,占據內存,release版本會把字符進行處理。

    ??臻g

    運行時,函數內部使用的變量,函數一旦返回,就釋放,生存周期是函數內

    堆空間

    運行時,可以自由,自我管理的分配和釋放的空間,生存周期是由程序員來決定

    分配:
    malloc(),一旦成功,返回分配好的地址給我們,只需要接受,對于這個新地址的讀法,由程序員靈活把握,輸入參數指定分配的大小,單位就是B。

    char *p;p = (char *)malloc(100); if(p == NULL){error }void fun() {char *p;p = (char *)malloc(100);return ; }int a[5]; malloc(5*sizeof(int))

    釋放:
    free§;

    只讀空間

    靜態空間,整個程序結束時釋放內存,生存周期最長

    C語言函數的使用

    函數概述

    一堆代碼的集合,用一個標簽去描述它

    函數 數組,函數具備3要素: int *p; int a[100];
    1、函數名 (地址)
    2、輸入參數
    3、返回值
    在定義函數時,必須將3要素告知編譯器。
    int fun(int,int,char)
    { xxx }

    如何用指針保存函數那?
    char *p;
    char (*p)[10];
    int (*p)(int,int,char);

    定義函數,調用函數

    int fun(int a,char b) {xxxx } int main() {fun(10,2); }char buf[100]; buf[10];

    輸入參數

    承上啟下的功能

    調用者:
    函數名(要傳遞的數據) //實參
    被調者:
    函數的具體實現
    函數的返回值 函數名(接收的數據) //形參
    {
    xx xxx
    }

    實參 傳遞給 形參
    傳遞的形式:
    拷貝

    值傳遞

    特點:

    void fun(int a) {a = xx;a = sha md5 yy }int main() {int a = 20;fun(a);printf a ==? }

    上層調用者 保護自己空間值不被修改的能力

    地址傳遞

    上層,調用者 讓下層 子函數 修改自己空間值的方式,類似結構體這樣的空間,函數與函數之間調用關系—> 連續空間的傳遞 (不傳地址的話,只是 拿來看一下,并不改變本身的值)

    void fun(char a); int main() {char a = 'e';fun(a);a == 'c' } void fun(char *b);int a = 10;fun(&a);a ===? 10int a; scanf("%d",a); scanf("%d",&a)

    將a的值傳遞給函數,不能保證a還為10

    連續空間的傳遞

    1、數組
    數組名 — 標簽
    實參:
    int abc[10];

    fun(abc)

    形參:
    void fun(int *p) void fun(int p[10])

    2、結構體
    結構體變量

    struct abc{int a;int b;int c;};
    struct abc buf;

    實參:
    fun(buf); fun(&buf)
    形參:
    void fun(struct abc a1) void fun(struct abc *a2)

    **" " —> 初始化const char *

    承上啟下的功能

    調用者:
    函數名(要傳遞的數據) //實參
    被調者:
    函數的具體實現
    函數的返回值 函數名(接收的數據) //形參
    {
    xx xxx
    }

    實參 傳遞給 形參
    傳遞的形式:
    拷貝

    值傳遞

    特點:

    void fun(int a) {a = xx;a = sha md5 yy }int main() {int a = 20;fun(a);printf a ==? }

    上層調用者 保護自己空間值不被修改的能力

    地址傳遞

    上層,調用者 讓下層 子函數 修改自己空間值的方式,類似結構體這樣的空間,函數與函數之間調用關系—> 連續空間的傳遞 (不傳地址的話,只是 拿來看一下,并不改變本身的值)

    void fun(char a); int main() {char a = 'e';fun(a);a == 'c' } void fun(char *b);int a = 10;fun(&a);a ===? 10int a; scanf("%d",a); scanf("%d",&a)

    將a的值傳遞給函數,不能保證a還為10

    連續空間的傳遞

    1、數組
    數組名 — 標簽
    實參:
    int abc[10];

    fun(abc)

    形參:
    void fun(int *p) void fun(int p[10])

    2、結構體
    結構體變量

    struct abc{int a;int b;int c;};
    struct abc buf;

    實參:
    fun(buf); fun(&buf)
    形參:
    void fun(struct abc a1) void fun(struct abc *a2)

    " " —> 初始化const char *
    char buf[10] —> 初始化char *

    總結

    以上是生活随笔為你收集整理的C语言重难点的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。