嵌入式0基礎開始學習 ⅠC語言(7)指針

0.問題引入

??????? int a = 5;? ?
?? ??? ?a = 1024; //把1024存放到變量a的地址中去
?? ??? ?b = a; // 取變量a的值,賦值給b
?? ??? ?? ===>在c語言中,任何一個變量,都有兩層含義
?? ??? ???????? (1)代表變量的存儲單元的地址:變量的地址 ===> lvalue
?? ??? ??? ??? ?(2)代表該變量的值: ===> rvalue
?? ??? ??? ??? ?
?? ??? ????? 對于變量的訪問,只有兩種情況
?? ??? ??? ? read: 從變量的地址中取值
?? ??? ??? ? write : 把一個數值,寫到變量的地址中去
?? ??? ??? ?
?? ??? ?問題:
?? ??? ?????? 如果我們知道了一個變量的地址,是不是我們就可以通過該變量的地址去訪問這個變量
?? ??? ??? ???????? 可以的
?? ??? ??? ??? ?如何通過一個變量的地址去訪問這個變量呢?
?? ??? ??? ??? ??? ====> 指針???? ??? ??? ???

1.對象的訪問方式

?????? (1)直接訪問:通過對象名去訪問
?? ???????? 直接訪問有一個缺陷?
?? ??? ??? ????? 直接訪問受對象的作用域的影響(限制)
?? ??? ??? ??? ?//?? 局部變量不是永久的,函數返回的時候,局部變量就會被刪除
?? ??? ??? ??? ?
?? ??? (2)間接訪問:通過對象的地址去訪問,指針訪問
?? ???????? 只要你知道了對象的地址,就可以去任何地方訪問它,不受作用域的影響?? ????

2.什么是指針?指針的概念???? ???????

??????? 存儲單元的地址:
?? ??? ?????????? 分配給每一個變量的內存單元都有一個編號,這個編號就是我們說的存儲單元的地址,
?? ??? ??? ??? ?? 并且是按字節來編址。
?? ??? ?
?? ??? ?在c語言中,指針的概念與地址的概念差不多,你可以認為指針就是一個地址,一個變量的地址
?? ??? ?我們也稱為變量的指針。
?? ??? ?
?? ??? ?& 取地址符:
?? ??? ???????? 單目運算符, ”取xxx對象的地址“
?? ??? ??? ??? ?
?? ??? ?通過一個對象的指針去訪問它,首先要解決 對象的指針(地址)的存儲問題
?? ??? ?這個時候需要定義一個變量來保存它的地址,這個變量我們稱為”指針變量“?? ????

3.指針變量

??????? 什么是指針變量?
?? ??? ???????? 指針變量也是一個變量,也是用來保存數據的,只不過指針變量是用來保存其他對象的地址的。
?? ??? ?如何定義一個指針變量?
?? ??? ?????? 回顧:?? 普通變量的定義
?? ??? ??? ??????????????????? 變量的類型??? 變量名;
?? ??? ??? ??? ??? ??? ?在定義指針變量的時候,為了區分在指針變量的前面加一個*,來表示他是一個指針變量
?? ??? ??? ??? ??? ??? ?
?? ??? ??? ?====》
?? ??? ??? ????? 指針變量的定義:
?? ??? ??? ??? ???????? 指向對象的類型 * 對象名
?? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ???? ”指向對象的類型“:
?? ??? ??? ??? ??? ??? ??? ??? ?指針變量指向的對象的類型,不是指針的類型。
?? ??? ??? ??? ??? ??? ??? ??? ?”指向“:
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? 假如一個變量p保存了變量a的地址,
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? 那么,我們就說p指向a
?? ??? ??? ??? ??? ??? ??? ??? ?例子:
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?int a? = 1024;
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? p = &a ;?? // 把a的地址賦值給p
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?// p保存了對象a的地址
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?// p 指向a
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?// p ---> 指針變量
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? 這個p該如何定義?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?? 指向對象的類型 * 指針變量名
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? typeof(a) * p
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ===> int * p;
?? ??? ??? ??? ??? ??? ??? ?練習:
??????????????????????????????????? char c[10];
?? ??? ??? ??? ??? ??? ??? ??? ??? ?char * p;
?? ??? ??? ??? ??? ??? ??? ??? ??? ?p = &c[9];
????????????????????????????????? 分析過程?? ?
?????????????????????????????????????????? p保存了c[9]的地址;
?????????????????????????????????????????? ====> p指向c[9]
??????????????????????????????????????????????? p是一個指針變量

4.與指針相關的運算符

??????????? & :取地址符
??????????? * :指向運算符
??????????????????? 單目運算符
??????????????????? 用法:
??????????????????????????? * 地址?? <=> 地址對應的那個變量(對象)
??????????????????????? int a;
??????????????????????? * a? // ERROR
?? ??? ??? ??? ??? ??? ?
??????????????????? 例子:
?????????????????????????? int a = 1024;
?????????????????????????? *(&a)? ===>? *對象a的地址
?? ??? ??? ??? ??? ??? ?????????? ===>? 地址對應的那個對象?? ??? ??? ??? ??? ??? ??? ??? ? ??? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ???? int b = *(&a);? <==> b = a
?? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ?so
?? ??? ??? ??? ??? ??? ???? *(&a) <==> *&a <==> a
?? ??? ??? ??? ??? ??? ??? ?* & ===>可以直接約掉
?? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ??? ?NOTE:
?? ??? ??? ??? ??? ??? ??? ????? & *a <==> a? ???? 不可以
?? ??? ??? ??? ??? ??? ??? ??? ? & * 不能約
?? ??? ??? ??? ??????? ?
?? ??? ??? ??? ??? ??? ?char ch ;
?? ??? ??? ??? ??? ??? ?* (&ch) = 'A'; // *(&ch) ==>ch ,在此處代表的是變量ch的左值,”變量的地址“
?? ??? ??? ??? ??? ??? ?char c = *&ch; // *(&ch) 在此處代表的是變量ch的右值,”變量的值“
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?
??????????????? 代碼分析:
??????????????????????????? int a = 5;
??????????????????????????? 假如我們要定義一個變量p,來保存a的地址,
?? ??? ??? ??? ??? ??? ??? ?int *p;
?? ??? ??? ??? ??? ??? ??? ?p = &a;???????????????????????? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ??? ?????????? // 把變量a 的地址賦值給p
?? ??? ??? ??? ??? ??? ??? ???????????? p是一個指針變量
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?那么,它也有左值,右值
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?p的右值:p的存儲單元中的內容? ===> &a
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?p的左值:p本身存儲單元的地址? ===> &p
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ??? ??? ??? ???? * p :在此處p代表 p的右值,p的值
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ???? * p <==>*(&a) <==> a;
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?a = 1024; <==> *(&a) ==>1024 ==> *p =1024
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ?請大家寫一個程序,來證明p的右值就是&a??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ??? ?#include <stdio.h>
?? ??? ??? ??? ??? ??? ??? ?int main()
?? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ?? ?
?? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ????

5.指針變量作為函數的參數

??????????? 練習:? 如下函數該這么設計?該怎么調用
??????????????????? void func(int *x,int *y)
??????????????????? {
?? ??? ??? ??? ??? ?? int temp;
????????????????????? temp = *x; // ===> temp = *(&a)
????????????????????? *x? = *y; // *(&a) = *(&b)
????????????????????? *y = temp; // *(&b) = temp ?? ??? ??? ??? ??? ? ?
?? ??? ??? ??? ??? ?? ?
?? ??? ??? ??? ??? ?}
??????????????????? void func1(int *x,int *y) // 不可以的? ?
??????????????????? {
?? ??? ??? ??? ??? ?? int *temp;
?? ??? ??? ??? ??? ?? temp = x;
?? ??? ??? ??? ??? ?? x= y;
?? ??? ??? ??? ??? ?? y = temp;
?? ??? ??? ??? ??? ?}?? ??? ??? ??? ??? ?
??????????????????? int main()
??????????????????? {
?? ??? ??? ??? ??? ???? int a = 5;
?? ??? ??? ??? ??? ??? ?int b = 6;
?? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ?int *p = &a;
?? ??? ??? ??? ??? ??? ?int *q = &b;
?? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ?func(p,q); //調用這個函數的目的是:為了交換變量a和b的值
?? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ?printf("a==%d\n",a);//6
?? ??? ??? ??? ??? ??? ?printf("b==%d\n",b);//5
?? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?}?? ??? ??? ??? ??? ?
?? ???? 傳的還是”值“,傳的還是”實參的值“,
??????? ”實參的值可能是某個對象的地址“

??????????????? 例子:
??????????????????????? void func(int *a,int *b)
??????????????????????? {
?? ??? ??? ??? ??? ??? ???? int *t; //定義了一個指針t,但是t沒有賦值,不知道這個t保存了
?? ??? ??? ??? ??? ??? ??? ?????????? 哪個對象的地址;不代表它里面沒有值
?? ??? ??? ??? ??? ??? ??? ??? ??? ?? 如果是一個指針變量的話,不知道它指向的對象是誰
?? ??? ??? ??? ??? ??? ??? ??? ??? ?? *t? ==>t指向的那一個對象
?? ??? ??? ??? ??? ??? ??? ??? ??? ??????? 如果我們去操作*t ,分為兩種情況
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? read :
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????????? int m = *t; //有可能t指向的那一個對象不可讀。
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?? // 可能導致內存的非法訪問 =>段錯誤
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? write:
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??????????? *t = 1024;//有可能t指向的那一個對象不可寫
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?? // 可能導致內存的非法訪問 =>段錯誤
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?????? ?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ???????? ?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?? ?
?? ??? ??? ??? ??? ??? ??? ?*t = *a; //可能導致”段錯誤“
?? ??? ??? ??? ??? ??? ??? ?*a =*b;
?? ??? ??? ??? ??? ??? ??? ?*b = *t; //可能導致”段錯誤“
?? ??? ??? ??? ??? ??? ?}?? ??? ??? ??? ??? ??? ?
?? ??? ???? 像這個例子中的t這樣的指針,我們稱之為”野指針“。
?? ??? ??? ?野指針:
?? ??? ??? ??????? 指向一個未知單元(未知對象)的指針,稱之為”野指針“
?? ??? ??? ??? ??? 使用野指針,可能造成內存的非法訪問 ===> 段錯誤
?? ??? ??? ??? ??? int *p;
?? ??? ??? ??? ?// *p = 1024;? 屬于操作野指針
?? ??? ??? ??? ?// int b = *p ; 屬于操作野指針
?????????????????? int a;
??????????????????? p = &a; // 不屬于操作野指針

??????????? 空指針:
??????????????????? NULL
?????????????????? 在計算機中,地址為0的存儲空間是不存在的
?????????????????? 如果一個指針的值為0(NULL),表示這個指針指向了
?????????????????? 空(NULL),像這中指向0(NULL)的指針,我們稱之為
?????????????????? 空指針
?????????????????? int *p = NULL;
?? ??? ??? ??? ??????? p它不是野指針
?? ??? ??? ??? ??? ?? ?
?? ??? ??? ??? ?段錯誤原因:內存的非法訪問
?? ??? ??? ??? ????????? (1)數組越界,可能導致段錯誤
?? ??? ??? ??? ??? ??? ?????? int a[10];
?? ??? ??? ??? ??? ??? ??? ?? a[100] = 1024;
?? ??? ??? ??? ??? ??? ? (2)非法使用指針(指針亂指)(野指針)

6.? 數組與指針

??????? 數組元素與普通變量是一樣的,也是有自己的地址。
??????? 數組元素也有左值和右值,并且數組元素的地址相鄰的。
????? ===>數組名可以代表首元素的地址(首地址)。
???????? 例子:
??????????????? int a[5];
????????????????????? a是一個數組名, 數組名a當作指針來看: a <===> &a[0]
?? ??? ??? ??? ??? ?? 我要定義一個指針變量p,來保存a[0]的地址
?? ??? ??? ??? ??? ?? 該如何定義p?
?? ??? ??? ??? ??? ? ?
?? ??? ??? ??? ??? ??? int *p = &a[0] //OK
?? ??? ??? ??? ??? ????????? 如果把數組名a當作指針來看, a ===> &a[0];
?? ??? ??? ??? ??? ??? ??? ? <===> p = a; // OK
?? ??? ??? ??? ??? ??? ??? ? a[0] = 1024;
?? ??? ??? ??? ??? ??? ??? ? <===> *p = 1024;
?? ??? ??? ??? ??? ??? ??? ? <===> *a = 1024;
?? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?p是指向a[0],那么能不能通過p去訪問a[1]?
?? ??? ??? ??? ??? ?????????? 可以的
?? ??? ??? ??? ??? ??? ??? ? ?
?? ??? ??? ??? ??? ??? ?*p?? ===>*&a[0] ==>a[0]
?? ??? ??? ??? ??? ??? ?a[0]和a[1]的地址是相鄰的
?? ??? ??? ??? ??? ??? ??????? p + 4 ==&a[1] ????不對的
?? ??? ??? ??? ??? ??? ?p + 1 ===> &a[1]
?? ??? ??? ??? ??? ??? ?????? 通過指針p來訪問a[1];
?? ?
??? 指針做加減的問題: int a[5]
??????????? p + i? (p是一個指針,i是一個整數)
?? ??? ??? ???????? 不是簡單的加減值,而是加減i個指向單元的長度
?? ??? ??? ?p+1? ===> 往后面挪了一個指向單元的長度
?? ??? ??? ??????? p = > &a[0]
?? ??? ??? ??? ??? p+1 => 往后面挪了一個int單元的長度
?? ??? ??? ??? ???????? (p+1) = >&a[1]
?? ??? ??? ?
?? ??? ??? ?例子:
?? ??? ??? ????? 有p = &a[0],把數值100賦值給a[0],有多少種表示方法?
?? ??? ??? ??? ??? int a[10];
?? ??? ??? ??? ??? int *p = &a[0];
?? ??? ??? ??? ?? ?
?? ??? ??? ??? ??? a[0] = 100;
?? ??? ??? ??? ??? *p = 100;
?? ??? ??? ??? ??? *&a[0]? = 100;
?? ??? ??? ??? ??? *a = 100;
?? ??? ??? ??? ??? **&p = 100;
?? ??? ??? ??? ??? **&a = 100;
?? ??? ??? ??? ??? p[0] = 100;
?? ??? ??? ??? ??? *(p+0) = 100;
?? ??? ??? ??? ??? *(a+0)= 100;
?? ??? ??? ??? ??? *(&a[1]-1) = 100;
?? ??? ??? ??? ??? .....
?? ??? ??? ??? ?? ?
?? ??? ??? ?練習:
?? ??? ??? ???????? int a[10] = {1,2,3,4,5,6,7,8,9,10};
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?int *p = &a[2];
?? ??? ??? ??? ??? ?通過指針p去訪問每一個元素的值,將其依次輸出。

7.多維數組與指針

??????????? (1)在C語言中所有數組都是一維數組
??????????? (2)數組名可以當作指向第0個元素類型的指針常量,
?? ??? ??? ????? 并且數值上為第0個元素的首地址
?? ??? ??? ??? ?
?? ??? ??? ??? ?假如有:
?? ??? ??? ??? ???????? int a[3][4]
?? ??? ??? ??? ??? ??? ??? //int [4] a[3]
?? ??? ??? ??? ??? ??? ??? a[0] _ _ _ _
?? ??? ??? ??? ??? ??? ??? a[1] _ _ _ _
?? ??? ??? ??? ??? ??? ??? a[2] _ _ _ _
?? ??? ??? ??? ??? ??? ?? ?
?? ??? ??? ??? ???? 表達式????? 表達式的含義
?? ??? ??? ??? ??? ?? a?????????? (1)當作指針
?? ??? ??? ??? ??? ?????????????????? &a[0]
?? ??? ??? ??? ??? ??? ??? ??? ?? (2)代表整個數組
?? ??? ??? ??? ??? ?
???????????????????? a[0]????????? a[0]又是一個一維數組名
????????????????????????????????????? (1)代表為a[0]的整個數組
????????????????????????????????????? (2)當作指針
???????????????????????????????????????????? &a[0][0]
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?
??????????????????? &a[0][0]?????? 元素a[0][0]的地址?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?
?????????????? -------------------------------------------------?? ??? ??? ??? ?
?? ??? ??? ????????? a+1?????????? 數組名a當作指針
?? ??? ??? ??? ??? ??????????????????? ==> &a[0] + 1
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ==> &a[1]
?? ??? ??? ??? ??? ??? ??? ??? ??? ???? 取整個一維數組a[1]的地址
?? ??? ??? ??? ??? ?&a[1]????????? 取整個一維數組a[1]的地址

???????????????????? &a????????????? 數組名a只能代表整個數組
????????????????????????????????????? &a:取整個二維數組的地址

???????????????????? &a+1?????????? 數組名a代表整個數組
??????????????????????????????????? &a+1 : 往后面挪了整個二維數組a的長度(12個int)
?? ??? ??? ??? ?------------------------------------------------
??????????????????? a[1]+2???????? a[1]是一個一維數組名,只能當作指針
?????????????????????????????????? ===>?? ?&a[1][0] + 2
?????????????????????????????????? ===> &a[1][2] :元素a[1][2]的地址
?????????????????? ?
??????????????????? *(a+1)+2???? *(&a[0]+1)+2
???????????????????????????????? ==> *(&a[1])+2
???????????????????????????????? ==> a[1] + 2
???????????????????????????? ??? ? ==> &a[1][0] + 2
???????????????????????????????? ==> &a[1][2] :元素a[1][2]的地址
??????????????? ------------------------------------------------
??????????????????? *(a[1]+2)????? a[1]是一個一維數組名,只能當作指針
??????? ??? ??? ??? ??? ??? ????? ==> *(&a[1][0] + 2)
?? ??? ??? ??? ??? ??? ??? ??? ? ==> *(&a[1][2])
?? ??? ??? ??? ??? ??? ??? ??? ? ==>a[1][2]:元素a[1][2]
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?*(*(a+1)+2)? ==> *(*(&a[1])+2)
?? ??? ??? ??? ??? ????????????? ==>*(a[1]+2)
?? ??? ??? ??? ??? ??? ??? ??? ? ==>*(&a[1][0]+2)
?? ??? ??? ??? ??? ??? ??? ??? ? ==>*(&a[1][2])
?? ??? ??? ??? ??? ??? ??? ??? ? ==>a[1][2]:元素a[1][2]
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?指針常量:
?? ??? ??? ??? ??? ????????? 指針本身不能夠改變,但是指向的空間里面的內容是可以改變的
?? ??? ??? ??? ??? ??? ??? ? 如: 數組名作為指針
?? ??? ??? ??? ??? ??? ??? ? int m,n;
?? ??? ??? ??? ??? ??? ??? ? int *const a = &m; // a就是一個指針常量
?? ??? ??? ??? ??? ??? ??? ? *a = 1024;// ok
?? ??? ??? ??? ??? ??? ??? ? a = &n ; // ERROR
?? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?常量指針:
?? ??? ??? ??? ??? ???????? 是一個指向常量的指針,指向的對象是常量,那個對象是不能改變的
?? ??? ??? ??? ??? ??? ??? ?但是指針是可以改變的(也就是說可以保存其他的地址)
?? ??? ??? ??? ??? ??? ??? ?如:? 字符串指針
?? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ??? ?int m = 1024,n;
?? ??? ??? ??? ??? ??? ??? ?const int *b = &m;? ===> int const *a;
?? ??? ??? ??? ??? ??? ??? ?*a = 250;//ERROR
?? ??? ??? ??? ??? ??? ??? ?a = &n ; // ok
?? ??? ??? ??? ??? ??? ????

8.指針數組與數組指針

??????????? (1) 指針數組
?? ??? ??? ???????? 指針數組是一個數組,只不過它里面的每一個元素都是相同類型的指針罷了!!!
?? ??? ??? ??? ??? ???? 定義數組:
?? ??? ??? ??? ??? ??? ?????????? 數組元素的類型?? 數組名[元素個數]
?? ??? ??? ??? ??? ??? ??? ??? ? ?
?? ??? ??? ??? ??? ??? ??? ?例子:
?? ??? ??? ??? ??? ??? ??? ?????? int * p[4]; //指針數組
?? ??? ??? ??? ??? ??? ??? ??? ????????? //定義了一個數組,數組名為p,里面含有4個元素
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? 每一個元素類型都是 int *.
?? ??? ??? ?(2) 數組指針
?? ??? ??? ???????? 數組指針是一個指針,只不過這個指針使用來指向一個數組的
?? ??? ??? ??? ??? ?(這個指針保存的地址是一個數組的地址罷遼!!!)
?? ??? ??? ??? ??? ??????? 例子:
?? ??? ??? ??? ??? ??? ????????? int a[4];
?? ??? ??? ??? ??? ??? ??? ??? ? 您能不能定義一個指針p來保存數組a的地址呢?
?? ??? ??? ??? ??? ??? ??? ??? ??????? 指針定義:
?? ??? ??? ??? ??? ??? ??? ??? ??? ????????????? 指向對象的類型 * p;
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? typeof(a) *p;
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? int [4] *p;
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? =>int (*p) [4];// p是一個指針,它指向的對象是一個int[4]類型的數組
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ?練習:1.
?? ??? ??? ??? ??? ?int a[10] = {1,2,3,4,5,6,7,8,9,10};
?? ??? ??? ??? ???? printf("a = %p, a + 1 = %p, &a + 1 = %p\n",
?? ??? ??? ??? ??? ?a, a + 1, &a + 1);
?? ??? ??? ??? ??? ?......
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?
?? ??? ??? ??????? 2.分析如下程序的輸出結果。
?? ??? ??? ??? ??? ?int a[5] = {1,2,3,4,5};
?? ??? ??? ??? ??? ?int * ptr = (int *)(&a + 1);
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?printf("%d? %d\n", *(a + 1), *(ptr - 1));//2 5
?? ??? ??? ??? ??? ?--------------------------------------
?? ??? ??? ??? ??? ?int a[5] = {1,2,3,4,5};
?? ??? ??? ??? ??? ?int * ptr = (int *)&a + 1;
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?printf("%d? %d\n", *(a + 1), *(ptr - 1)); // 2 1
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?3.
?? ??? ??? ??? ??? ??? ?int b[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
?? ??? ??? ??? ??? ??? ??? ?//int[4] b[3]
?? ??? ??? ??? ??? ??? ??? ?//b[0] _ _ _ _
?? ??? ??? ??? ??? ??? ??? ?//b[1] _ _ _ _
?? ??? ??? ??? ??? ??? ??? ?//b[2] _ _ _ _
?? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ?printf("**b = %d, *(b[0] + 1) = %d\n",
?? ??? ??? ??? ??? ??? ??? ?**b, *(b[0] + 1) ); ?
?? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ??? ?**b : b當作一個指針
?? ??? ??? ??? ??? ??? ??? ???? ===>**(&b[0])
?? ??? ??? ??? ??? ??? ??? ??? ?===>*b[0]? //b[0]又是一個數組名,當指針來看
?? ??? ??? ??? ??? ??? ??? ??? ?===>*(&b[0][0])
?? ??? ??? ??? ??? ??? ??? ??? ?===>b[0][0]
?? ??? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ??? ?*(b[0]+1):把b[0]當指針來看
?? ??? ??? ??? ??? ??? ??? ???? ===> *(&b[0][0]+1)
?? ??? ??? ??? ??? ??? ??? ??? ?===>b[0][1]
?? ??? ??? ??? ??? ??? ??? ?? ?
?? ??? ??? ??? ??? ??? ??? ??? ? ?
?? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?4. 有int b[3][4]; 假如要定義一個指針變量p,
?? ??? ??? ??? ??? ??? ?來保存b[0][0]的地址,該如何定義?
?? ??? ??? ??? ??? ??? ??? ??? ?//int[4] b[3]
?? ??? ??? ??? ??? ??? ??? ??? ?//b[0] _ _ _ _
?? ??? ??? ??? ??? ??? ??? ??? ?//b[1] _ _ _ _
?? ??? ??? ??? ??? ??? ??? ??? ?//b[2] _ _ _ _
?? ??? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ??? ?typeof(b[0][0]) *p;
?? ??? ??? ??? ??? ??? ??? ? ====> int *p;
?? ??? ??? ??? ??? ??? ??? ? p = &b[0][0];
?? ??? ??? ??? ??? ??? ??? ????? //typeof(p) ==> int *
?? ??? ??? ??? ??? ??? ??? ? p = b[0]; // ok

9.字符串指針?? ??? ???

? ??? ? ????
?? ??? ?字符串是什么?
??????????? 字符串就是一串字符,在c語言中是沒有字符串類型的。
??????????? C語言的字符串是通過 char *(字符型指針)來實現的。
??????????? C語言的字符串,是用”“(雙引號)引起來的一串字符來表示。
??????????? 并且字符串后面默認會加一個’\0',表示字符串結束的標志。
?????????????????? 如;
??????????????????????? ”abcde“? ==>5
??????????????????????? "1"???? ==> 1
??????????????????????? '123'?? 不是字符串,也不是字符啊
??????????????????????? '\012'? 不是字符串 ,是字符?? ??? ??? ??? ??? ??? ?
??????????????????????? "\012"?? ?==>是字符串,有一個字符 ?
??????????????????????? "" ?? ??? ?==>是字符串,空串?? ?
?? ??? ??? ??? ?
??????????? 只需要保存字符串的首地址(首字符的地址)就可以了?? ?
?? ??? ??? ?從首地址開始找到第一個’\0',前面的這些字符就是字符串里面的字符
??????????????? C語言中的字符串(如:”sssssss“)保存在一個叫做.rodata(只讀數據)的內存區域中。
?
??????????? 如;
??????????????? "12345"
??????????????? 在程序運行時,系統會為這個字符串在.rodata中分配6個字節大小的空間給它
?????????????? ?
??????????????? ”12345“的值,就是首字符的地址。
??????????????? typeof(”12345“)
??????????????????? ====》typeof(&’1‘)
??????????????????? ====》typeof('1') *
??????????????????? ====> const char *

??????????? 例子:
??????????????????? char *p = "12345";
??????????????????????? p保存的是字符串首字符的地址,&’1‘
??????????????????????? 那么咱們是不是可以通過指針p來訪問’1‘呢
???????????????????????????? 可以
????????????????????????? 因為: p = &’1‘;
????????????????????????? char m = *p ; <===> m = '1'
????????????????????????? *p = 'A';//ERROR? 因為p指向的對象是一個常量,不可以改變的
?? ??? ??? ??? ??? ??? ?????? 字符串就相當于一個常量指針
??????????????????? ?
?? ??? ??? ??? ??? ?問題:
?? ??? ??? ??? ??? ?????? 字符’1‘和’2‘的地址是不是連續的呢?
?? ??? ??? ??? ??? ??? ???????? 是連續的
?? ??? ??? ??? ??? ??? ??? ?既然是連續的,那么咱們也可以通過指針p來訪問’2‘
?? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ??? ???? p = &’1‘;
?? ??? ??? ??? ??? ??? ??? ??? ?p+1 ===>往后面挪了一個char類型的單元長度?? 《===》 &’2‘
?? ??? ??? ??? ??? ??? ??? ??? ?*(p+1) ==> *(&'2') ===> '2'
?? ??? ??? ??? ??? ??? ??? ??? ?printf("%c\n",*p); // 1
?? ??? ??? ??? ??? ??? ??? ??? ?printf("%c\n",*(p+1));// 2
?? ??? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ??? ??? ?p+= 1; // OBJK ?
?? ??? ??? ??? ??? ??? ??? ??? ?==>
?? ??? ??? ??? ??? ??? ??? ??? ????? p = p+1;
?? ??? ??? ??? ??? ??? ??? ??? ??? ? p = &'2';
?? ??? ??? ??? ??? ??? ??? ??? ?*(p+1) = 'B';//ERROR
?????? ?
??????? 字符數組:
??????????????? char s[5] ={'a','b','c','d','e'};
??????????????????? sizeof(s) == 5
??????????????????? char ch = *(s+1); <==> ch = s[1]
??????????????????? *(s+1) = 'B' ; // <===> s[1] = 'B'
??????????????????? s+= 1; //ERROR ==》 s = s+1 因為s是一個指針常量(數組名作為指針)為指針常量

??????????????? char s[] = {'a','b','c','d','e'};
???????????????????? sizeof(s) == 5;
???????????????????? 可以省略元素個數
??????????????? char s[] = {"abcde"};
????????????????????? <===>? char s[] = {'a','b','c','d','e','\0'};
???????????????????????????? sizeof(s) = 6;
??????????????????????????? *(s+1) = ’B‘ ; // 可以,因為s是一個字符數組,數組區域是可讀可寫的
??????????????????????????? printf(”%s\n“,(s+1)); //Bcde?? ?
?? ??? ??? ??? ??? ??? ??? ?
??????????????????????????? %s -> char *
??????????????????????????? 把后面的哪個地址(指針)當作是一個字符串的首地址,一個一個字符的輸出,
??????????????????????????? 直到遇到'\0'結束,’\0' 不打印?? ?

??????????? 練習;
??????????????????? 1.分析如下程序的輸出結果
???????????????????? ?
??????????????????????? p = "abcde";
??????????????????????? printf("%s\n",p);//abcde

??????????????????????? char s[] = "12345";
??????????????????????? s[1] = ’B‘;
??????????????????????? printf("%s\n",s);//1B345

??????????????????? 2.寫一個函數,用來求一個字符串的長度(包含了多少個有效字符)
?????????????????? ??? ?(1)確定函數名
?? ??? ??? ??? ??? ??? ???? My_Strlen : 用來求一個字符串的長度
??????????????????????? (2)確定參數列表(形參列表)
?? ??? ??? ??? ??? ??? ???? const char *s
??????????????????????? (3)確定返回值的類型
?? ??? ??? ??? ??? ??? ???? 返回值:
?? ??? ??? ??? ??? ??? ??? ???????? 有效字符的個數(int)
??????????????????????? (4)代碼的實現

??????????????????????????? int My_Strlen(const char *s)
??????????????????????????? {
?? ??? ??? ??? ??? ??? ??? ??? int count = 0;
?? ??? ??? ??? ??? ??? ??? ??? while(*s) // *s !='\0'
?? ??? ??? ??? ??? ??? ??? ??? {
?? ??? ??? ??? ??? ??? ??? ?????? count ++;
?? ??? ??? ??? ??? ??? ??? ??? ?? s++;
?? ??? ??? ??? ??? ??? ??? ??? }
?? ??? ??? ??? ??? ??? ??? ??? return count;
?? ??? ??? ??? ??? ??? ??? ?}?? ?
??????????????????????????? int main()
???????????????????????????? {
?? ??? ??? ??? ??? ??? ??? ????? char q="123\0a0345";?? ??? ??? ??? ??? ??? ??? ??? ? ?
?? ??? ??? ??? ??? ??? ??? ??? ? scanf("%s",q);
?? ??? ??? ??? ??? ??? ??? ??? ?// int a ;
?? ??? ??? ??? ??? ??? ??? ??? ?// a = My_Strlen();
?? ??? ??? ??? ??? ??? ??? ??? ?// printf(a)
?? ??? ??? ??? ??? ??? ??? ??? ?printf("%d\n",My_Strlen((const char *)q));
?? ??? ??? ??? ??? ??? ??? ? }

10.幾個常用的字符串的處理函數(標準庫里面的)

(1)strlen :用來求一個字符串的長度

???????????? #include <string.h>

???????????? int strlen(const char *s);
?? ??? ??? ?
?? ??? ??? ? @s : 要計算長度的那一個字符串的首地址
?? ??? ??? ? const char * 類型: 表示在程序運行的過程中,指針指向的字符串不能被修改
?? ??? ??? ? 返回值:? 返回字符串的有效字符個數(不包括‘\0’);
?? ??? ??? ?
?? ??? ??? ? 例子:
?? ??? ??? ???????? strlen("abcde") == 5
?? ??? ??? ??? ??? ?char s[4] = {'1','0'};
?? ??? ??? ??? ??? ???? sizeof(s) == 4
?? ??? ??? ??? ??? ??? ?strlen(s) == 2
?? ??? ??? ??? ??? ?strlen("abcd\nabc") == 8
?? ??? ??? ??? ??? ?strlen("123\123abc\0abc") == 7
?? ??? ??? ??? ??? ?strlen("123\01a3abc\0abc") == 9
?? ??? ??? ??? ??? ?strlen("123\000abc") ==3
?? ??? ??? ??? ??? ?strlen("123\0x123") == 3
?? ??? ??? ??? ??? ?strlen("123\x123456gad") == 7

(2)strcpy/strncpy

??????? 字符串拷貝函數
?? ??? ?? NAME
?????? strcpy, strncpy - copy a string

SYNOPSIS
?????? #include <string.h>

?????? char *strcpy(char *dest, const char *src);
?? ????? strcpy: 用來把src指向的字符串,拷貝到dest指向的空間中去,直到遇到'\0'結束。
?? ??? ?
?? ????? @dest: 目的地(dest必須是一個可寫的空間)
?? ??? ? @src : 從哪里來
?? ??? ? 返回值:
?? ??? ????????? 返回拷貝之后,目的地字符串的首地址
?? ??? ??? ??? ?
?? ??? ??? ?例子:
?? ??? ??? ?????? char s[6];
?? ??? ??? ??? ?? strcpy(s,"12345");
?? ??? ??? ??? ?? printf("%s\n",s); //12345
?? ??? ??? ??? ? ?
?? ??? ??? ??? ?? char *p = "abcde";
?? ??? ??? ??? ?? char *q = "12345";
?? ??? ??? ??? ?? strcpy(p,q); //ERROR
?? ??? ??? ??? ? ?
?? ??? ??? ?strcpy 有一個小小的BUG!!!
?? ??? ??? ?因為他沒有考慮到數組越界的問題,有可能會導致內存的非法訪問
?? ??? ??? ?
?? ??? ? char *strncpy(char *dest, const char *src, size_t n);
?????????? ?
?? ??? ??? ?strncpy: 為了解決strcpy的這個bug的情況,功能是類似的,只不過
?? ??? ??? ?????????? 它頂多拷貝n個字符到 dest
?? ??? ??? ??? ??? ? ?
?? ??? ??? ??? ??? ?? 到底拷貝多少字符?(<=n)
?? ??? ??? ??? ??? ?? (1)遇到了\0拷貝結束的,此時\0也會被拷貝
?? ??? ??? ??? ??? ?? (2)已經拷貝了n個字符(后面的\0不會自動拷貝,除非最后一個字符是\0)
?? ??? ??? ??? ??? ? ?
?? ??? ??? ??? ?例子:
?? ??? ??? ??? ?????? char s[10];
?? ??? ??? ??? ??? ?? strncpy(s,"1234567890",10);
?? ??? ??? ??? ??? ? ?
?? ??? ??? ??? ??? ?? strncpy(s,"123",10);
?? ??? ??? ??? ??? ? ?
?? ??? ??? ??? ?練習: ?
?? ??? ??? ??? ?????? char s1[8]
?? ??? ??? ??? ??? ?? char s2[8] = {"ABCDE"};
?? ??? ??? ??? ??? ?? strncpy(s1,"123456789",8);
?? ??? ??? ??? ??? ? ?
?? ??? ??? ??? ??? ?? printf("%s\n",s1);
?? ??? ??? ??? ??? ?? printf("%s\n",s2);

(3)strcmp/strncmp

??????????? 字符串的比較函數
??????????? 那么字符串該如何比較勒?
??????????????????????? 一個一個字符進行PK對應的ASCII的值
??????????????????????????????? if? c1 >c2
??????????????????????????????????????? 返回 >0
??????????????????????????????? if? c1 < c2
??????????????????????????????????????? 返回 < 0
??????????????????????????????? if? c1 == c2
??????????????????????????????????????? 則繼續比較下一個字符,
??????????????????????????????????????? 如果全部相等則返回0

??????????????????????????? strcmp("123","ABC"); <0
??????????????????????????? strcmp("123","123\0ABC"); ==0
??????????????????????????? strcmp("1234","123"); >0
????????????????????????? ?
??????????????????????????? char *s = "GONG";
??????????????????????????? strncmp(s,"GONGJIANWEN",4) ==0

???????????????? #include <string.h>

?? ??? ??? ??? ??? int strcmp(const char *s1, const char *s2);

?? ??? ??? ??? ??? int strncmp(const char *s1, const char *s2, size_t n);
?? ??? ??? ??? ?? ?
?? ??? ??? ??? ???????????? strncmp它的功能與strcmp類似,
?? ??? ??? ??? ??? ??? ??? ?只不過它只比較s1,s2前面的n個字符
?? ??? ??? ??? ??? ??? ??? ?
(4)strcat/strncat

??????????? NAME
?????? strcat, strncat - concatenate(連接) two strings

SYNOPSIS
?????? #include <string.h>

?????? char *strcat(char *dest, const char *src);

?????? char *strncat(char *dest, const char *src, size_t n);
?? ??? ??? ??? ??? ?
???????????????????? strcat: 用來把src指向的字符串,拷貝到dest指向的字符串的末尾
??????????????????? ??? ?
???????????????????? @dest :指向目標字符串(一段可寫的空間)
???????????????????????????? dest指向的存儲空間必須要足夠的大,why?(越界)
???????????????????? @src? :指向原始字符串(表示將要被拷貝的那一個字符串)
???????????????????? 返回值:
???????????????????????????? 如果成功,返回連接后的字符串的首地址dest
???????????????????????????? 如果失敗,返回NULL

??????????????? 例子:
????????????????????? char s1[12] = {"ABCD"};
????????????????????? strcat(s1,"12345");
????????????????????? printf("%s\n",s1);//ABCD12345
?????????????????????? ?
??????????????????????? 當然這個函數也有一個小小的BUG,你懂的
??????????????????????? so strncat 就是用來修復strcat的這個bug的?? ?
?????? ?
??????????????????? strncat :
????????????????????????????? 把src指向的字符串拷貝到dest指定的字符串的末尾
????????????????????????????? 但是最多拷貝n個字符
??????????????????????????? (1)遇到\0拷貝結束,此時\0也會被拷貝
??????????????????????????????????? char s1[12] = {"ABCD"};
??????????????????????????????????? strncat(s1,"12345",8);//ABCD12345
??????????????????????????? (2)如果要是沒有遇到\0,但是以及拷貝了n個字符了,也結束
??????????????????????????????????? char s1[12]={"ABCD"};
???????????????????????? ??? ??? ??? ?strncat(s1,"123456789",8); //ABCD12345678

??????????? 練習:
??????????????????? 分析如下程序的輸出結果
??????????????????????????? char s[12];
??????????????????????????? strcat(s,"12345");
??????????????????????????? printf("%s\n",s); //隨機的值
?? ??? ??? ??? ??? ??? ??? ?
??????????????????? 寫一個函數,把一個十進制的數字字符串,轉成一個整數
??????????????????????????????? "12345"
??????????????????????????????????????? =>12345
??????????????????????????????? "-12345"
??????????????????????????????????????? =>-12345
??????????????????????????????? "+12345"
??????????????????????????????????????? =>12345?? ??? ??? ??? ??? ??? ??? ??? ?
?????????????????????? ?
?? ??? ??? ??? ??? ??? ???? /*
?? ??? ??? ??? ??? ??? ??? ???? my_atoi : 將一個十進制的數組字符串,轉換成一個整數
?? ??? ??? ??? ??? ??? ??? ??? ?@s :指向十進制數組字符串的? const char *s
?? ??? ??? ??? ??? ??? ??? ??? ?返回值:? 整數值
?? ??? ??? ??? ??? ??? ??? ?*/
?? ??? ??? ??? ??? ??? ??? ?int my_atoi(const char *s)
?? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ????? int minux = 0; //符號?? 0 --負數?? 1 -- 正數
?? ??? ??? ??? ??? ??? ??? ??? ? int d = 0; // 保存當前位的數值
?? ??? ??? ??? ??? ??? ??? ??? ? int num = 0; //整數的值
?? ??? ??? ??? ??? ??? ??? ????? if(*s == '-')
?? ??? ??? ??? ??? ??? ??? ??? ? {
?? ??? ??? ??? ??? ??? ??? ??? ???? minus = 0;
?? ??? ??? ??? ??? ??? ??? ??? ??? ?s++;
?? ??? ??? ??? ??? ??? ??? ??? ? }
?? ??? ??? ??? ??? ??? ??? ??? ? else if(*s == '+')
?? ??? ??? ??? ??? ??? ??? ??? ? {
?? ??? ??? ??? ??? ??? ??? ??? ???? minus = 1;
?? ??? ??? ??? ??? ??? ??? ??? ??? ?s++;
?? ??? ??? ??? ??? ??? ??? ??? ? }
?? ??? ??? ??? ??? ??? ??? ??? ? else
?? ??? ??? ??? ??? ??? ??? ??? ? {
?? ??? ??? ??? ??? ??? ??? ??? ???? minus = 1;
?? ??? ??? ??? ??? ??? ??? ??? ? }
?? ??? ??? ??? ??? ??? ??? ??? ? while(*s) // *s!='\0'
?? ??? ??? ??? ??? ??? ??? ??? ? {
?? ??? ??? ??? ??? ??? ??? ??? ???? d = *s-'0';
?? ??? ??? ??? ??? ??? ??? ??? ??? ?num = num *10 +d;
?? ??? ??? ??? ??? ??? ??? ??? ??? ?s++;
?? ??? ??? ??? ??? ??? ??? ??? ? }
?? ??? ??? ??? ??? ??? ??? ??? ? if(minus==0)
?? ??? ??? ??? ??? ??? ??? ??? ? {
?? ??? ??? ??? ??? ??? ??? ??? ???? num = num *(-1);
?? ??? ??? ??? ??? ??? ??? ??? ? }
?? ??? ??? ??? ??? ??? ??? ??? ? return num;
?? ??? ??? ??? ??? ??? ??? ?}
?????????????????? ??? ??? ?int main()
??????????????????????????? {
?? ??? ??? ??? ??? ??? ??? ??? char s[256];
?? ??? ??? ??? ??? ??? ??? ??? scanf("%s",s);
?? ??? ??? ??? ??? ??? ??? ??? printf("%d\n",my_atoi((const char *)s);
?? ??? ??? ??? ??? ??? ??? ??? //printf("%d\n",atoi());
?? ??? ??? ??? ??? ??? ??? ?}?? ?

??????????????? 其實呢,atoi這個函數是標準庫中的一個函數,大家是可以直接去用的,
?? ??? ?NAME
atoi, atol, atoll - convert a string to an integer

SYNOPSIS
?????? #include <stdlib.h>

?????? int atoi(const char *nptr);
?????? long atol(const char *nptr);
?????? long long atoll(const char *nptr);

??????? 在c語言中,不僅是變量,數組有地址,其實我們的函數也是有地址的。
?? ??? ?只要是有地址的東西,那么我們就可以定義一個指針變量去保存這個地址
?? ??? ?并且可以通過這個這個指針去訪問指向的對象。
?? ??? ?
?? ??? ????? 函數地址 ----> 函數指針???? ??

11.函數指針

??????? 什么是函數指針?
?? ??? ???????? 函數指針也是一個指針,只不過這個指針指向的是一個函數
?? ??? ??? ??? ?也就是說這個指針保存了函數的地址
?? ??? ??? ??? ?
?? ???? (1)函數指針該如何定義
?? ??? ??????? 指針定義:
?? ??? ??? ???????????? 指向對象的類型 * 指針變量名;
?? ??? ??? ??? ?函數的類型如何表述?
?? ??? ??? ??? ???????? 函數的類型三要素:
?? ??? ??? ??? ??? ??? ???????? 函數的返回值類型? (函數的參數類型列表)
?? ??? ??? ??? ??? ??? ??? ?例子:
?? ??? ??? ??? ??? ??? ??? ?????? int sum(int a,int b);
?? ??? ??? ??? ??? ??? ??? ??? ?? int (int , int)===>這個是一個類型,是用來描述一個類似與sum函數的!
????????????????????????????? ?
????????????????????????????????? int * abc(int a,float b)
????????????????????????????????? {}
????????????????????????????????? 描述abc的類型:
??????????????????????????????????????????????? 函數的返回值類型 (函數的參數類型列表)
??????????????????????????????????????????????????? int * (int,float)
??????????????????????????????????????????????????? ====> 是一個返回int*型,帶一個int和float的函數類型

??????????????????????????????????????????????? 定義一個指針變量q,用來保存abc的地址:
??????????????????????????????????????????????????????? 指向對象的類型 *q;
??????????????????????????????????????????????????????? typeof(abc) *q;
??????????????????????????????????????????????????????? ===>int * (int ,float) *q;
??????????????????????????????????????????????????????? ===>int * *q(int , float);
??????????????????????????????????????????????????????? ===>int * (*q)(int,float);

????????????????????????????????? 需要定義一個指針變量p,來保存函數sum的地址,該如何定義呢?
??????????????????????????????????????????? int (*p)(int,int);
??????????????????????????????????????????? 指向對象的類型 *p;
??????????????????????????????????????????? typeof(sum)* p;
??????????????????????????????????????????? ===>int (int,int)* p;
??????????????????????????????????????????? ===>int (*p)(int ,int);
?????????????????????????????? ?
??????????????????????? 函數指針的定義方法;
??????????????????????????????????? 指向函數的返回值類型 (*指針變量名)(指向函數的形參類型列表);
??????????????????????????????? 例子;
?????????????????????????????????? 1.? char ** func(void)
?????????????????????????????????????? {}
????????????????????????????????????? 請大家定義一個函數指針變量p,來保存函數func的地址
?? ??? ??? ??? ??? ??? ??? ??? ??? ???? char ** (*p)(void);
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ??????????? 2.請各位大佬定義一個指針變量q,來保存如下函數的地址
?? ??? ??? ??? ??? ??? ??? ??? ??????? 數組名a作為函數的參數,是當作指針來看的
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? => &a[0]?? typeof(&a[0]) ==> int *
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? //int arr_sum(int * a,int n)
?? ??? ??? ??? ??? ??? ??? ??? ????? int arr_sum(int a[],int n);
?? ??? ??? ??? ??? ??? ??? ??? ??? ? {}
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? => int (*q)(int *,int);
?? ??? ??? ??? ??? ??? ??? ??? ??? ?? ?
?? ??? ?(2)該怎么將函數的地址賦值給函數指針變量呢?
????????????????? p -> 函數指針
????????????????? p = 函數的地址
??????????????? 函數的地址怎么去獲取呢?
??????????????????? &對象名 ==> 取對象的地址

??????????????? 函數的地址:
??????????????????????? &函數名
??????????????????????? or
??????????????????????? 函數名:在c語言中,函數名本身就代表函數的首地址
??????????????????? 例子:
??????????????????????????? int sum_array(int *a,int n)
??????????????????????????? {}
??????????????????????????? //定義一個函數指針p
??????????????????????????? int (*p)(int *,int);
??????????????????????????? //將函數sum_array的地址賦值給p;
??????????????????????????? p = &sum_array;
??????????????????????????? //or
??????????????????????????? p = sum_array;
??????????????????????????????????????? //此時p指向函數sum_array

???????? (3)怎么通過函數指針取訪問這一個函數呢?
??????????????????? 函數調用:
????????????????????????????? 函數名(實參列表);
??????????????????? a,
???????????????????????? p = sum_array;
???????????????????????? sum_array(a,5);
??????????????????????? <==> p(a,5);

??????????????????? b,
?? ??? ??? ??? ??? ????? p = &sum_array;
?? ??? ??? ??? ??? ??? ? *p = *&sum_array;
?? ??? ??? ??? ??? ??? ? sum_array(a,5);
?? ??? ??? ??? ??? ??? ? ===>(*p)(a,5);
?? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ?結論:?? ?通過函數指針去調用指向的函數,有兩種方式
?? ??? ??? ??? ??? ??? ??? ? p為函數的指針
?? ??? ??? ??? ??? ??? ??? ? (1)p(實參列表)
?? ??? ??? ??? ??? ??? ??? ? (2)(*p)(實參列表)
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?練習;
?? ??? ??? ??? ??? ?????? 1.首先寫一個函數用來求一維數組中所有元素之和
?? ??? ??? ??? ??? ??? ???? 然后在main中定義一個指針p,通過p去調用sum_array.
?? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ??? ?#include <stdio.h>
?? ??? ??? ??? ??? ??? ??? ?//int sum_array(int a[],int n)
?? ??? ??? ??? ??? ??? ??? ?int sum_array(int *a,int n)
?? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ???? int i,sum=0;
?? ??? ??? ??? ??? ??? ??? ??? ?for(i=0;i<n;i++)
?? ??? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ??? ??? sum += a[i];
?? ??? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ??? ??? ?return sum;
?? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ??? ?int main()
?? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ??? int m[10] = {0,1,2,3,4,5,6,7,8,9};
?? ??? ??? ??? ??? ??? ??? ??? int (*p)(int *,int);
?? ??? ??? ??? ??? ??? ??? ??? p = &sum_array;
?? ??? ??? ??? ??? ??? ??? ??? int n = *p(m,10);
?? ??? ??? ??? ??? ??? ??? ??? printf("%d\n",n);
?? ??? ??? ??? ??? ??? ??? ?}

12.數組作為函數的參數的問題

??????????? 數組作為函數的參數的話,數組名都是當作指針來看!!!
?????????? ?
??????????? 把數組作為函數的形參:
??????????????????? 一維數組
?????????????????????????????? a,數組元素類型 數組名[] , 元素個數
?????????????????????????????? b,數組元素類型 * 指針變量名 ,元素個數

??????????????????? 二維數組
?????????????????????????????? a,數組元素類型 數組名[][列數] ,行數
?????????????????????????????? b,數組元素類型 (*指針變量名)[列數],行數
??????????????????????? ??? ??? ??? ??? ??? ??? ??? ?? ?
?? ??? ??? ??? ??? ?練習:
????????????????????????? 首先寫一個函數(sum_2_array)用來求二維數組中所有元素之和,
????????????????????????? 然后,在main中定義一個函數指針q,通過q來調用sum_2_array.?? ??? ??? ??? ??? ??? ? ?
?? ??? ??? ??? ??? ??? ??? ?int sum_2_array(int (*a)[4], int m)
?? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ??? ?int i, j ;
?? ??? ??? ??? ??? ??? ??? ??? ?int sum = 0;
?? ??? ??? ??? ??? ??? ??? ??? ?for(i = 0; i < m; i++)
?? ??? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ??? ??? ?for(j = 0; j < 4; j++)
?? ??? ??? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?sum += a[i][j];
?? ??? ??? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ??? ??? ?}

?? ??? ??? ??? ??? ??? ??? ??? ?return sum;
?? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ??? ?int main()
?? ??? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ??? ?int m[10] = {0,1,2,3,4,5,6,7,8,9};

?? ??? ??? ??? ??? ??? ??? ??? ?//定義一個函數指針p,來保存sum_array
?? ??? ??? ??? ??? ??? ??? ??? ?int? (* p)(int *, int );

?? ??? ??? ??? ??? ??? ??? ??? ?//將函數的地址賦值給 p
?? ??? ??? ??? ??? ??? ??? ??? ?p = &sum_array; //p = sum_array

?? ??? ??? ??? ??? ??? ??? ??? ?//通過p來調用sum_array函數
?? ??? ??? ??? ??? ??? ??? ??? ?int n = p(m, 10);
?? ??? ??? ??? ??? ??? ??? ??? ?printf("%d\n", n);
?? ??? ??? ??? ??? ??? ??? ??? ?int x = (*p)(m, 10);
?? ??? ??? ??? ??? ??? ??? ??? ?printf("%d\n", n);

?? ??? ??? ??? ??? ??? ??? ??? ?int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};

?? ??? ??? ??? ??? ??? ??? ??? ?//定義一個函數指針q,來保存sum_2_array
?? ??? ??? ??? ??? ??? ??? ??? ?int? (*q)(int (*)[4], int);

?? ??? ??? ??? ??? ??? ??? ??? ?//將函數的地址賦值給 q
?? ??? ??? ??? ??? ??? ??? ??? ?q = &sum_2_array; //q = sum_2_array

?? ??? ??? ??? ??? ??? ??? ??? ?//通過函數指針q來調用它所指向的那一個函數
?? ??? ??? ??? ??? ??? ??? ??? ?int y = q(a, 3);
?? ??? ??? ??? ??? ??? ??? ??? ?//int y = (*q)(a, 3);
?? ??? ??? ??? ??? ??? ??? ??? ?printf("%d\n", y);
?? ??? ??? ??? ??? ??? ??? ?}
??????????? ?
??????????????? 保存普通變量地址的? 變量 ==> 指針變量
??????????????? 指針變量也有地址,那么保存指針變量的地址的? 變量 ==> 二級指針???

13.二級指針以及多級指針

??????????????? int a= 1024;
??????????????? 可以定義一個指針變量p來保存a的地址
?? ??? ??? ??? ??? ?int *p;
?? ??? ??? ??? ??? ?p = &a; //p指向a

?????????? ??? ?p本身也有地址,我們可以定義一個指針變量p2來保存p的地址:
??????????????????? typeof(p) *p2;
??????????????????? int * *p2;
???????????????????????? // p2二級指針,它保存的是一個一級指針的地址
???????????????????????? //要分清楚到底是幾級指針,怎么去區分?
???????????????????????? // QTMD,你只要知道他是一個指針,(保存的是誰的地址)就可以了
??????????????????? p2 = &p; //p2指向p
??????????????????? **p2 = **&p = *p = *&a = a

14.main 函數的參數的問題

??????? int main()
??????? {}?? ?
??? 在linux下面,程序運行的時候,可以帶參數的,只不過所有的參數都當作是字符串來處理
??????? 如:
?? ??? ?????? ”./a.out“ "123""456""789"......
?? ??? ??? ?? 參數多個字符串 ==>字符串的數組
?? ??? ??? ? ?
?? ??? ??? ?? char * argv[] ={"./a.out","123","456”,“789”};
?? ??? ??? ? ?
?? ??? ??? ?在運行main函數的時候,可以把上面的那個數組傳遞給main函數的
?? ??? ??? ?so
?? ??? ??? ?在linux下面的c語言程序的main的參數可以有如下定義:
?? ??? ??? ?元素個數,數組元素類型 數組名[]
?? ??? ??? ?or
?? ??? ??? ?元素個數,數組元素類型 * 指針變量名
?? ??? ??? ?
?? ???? ==》
?? ??? ????? main函數的寫法:
?? ??? ??? ????????? int main(int argc,char *argv[])
?? ??? ??? ??? ??? ? {}
?? ??? ??? ??? ??? ? or
?? ??? ??? ??? ??? ? int main(int argc,char **argv)
?? ??? ??? ??? ??? ? {}
?? ??? ?==》
?? ??? ???? 在程序運行時,給main函數傳遞的參數,它在main函數中是如何表示的呢?
?? ??? ??? ?? ./a.out 123 456
?? ??? ??? ???????? int main(int argc,char *argv[])
?? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ???? //char *argv[] = {"./a.out","123","456","789"};
?? ??? ??? ??? ??? ??? ?//int argc = 4;
?? ??? ??? ??? ??? ??? ?//argv[0] -> "./a.out";
?? ??? ??? ??? ??? ??? ?//argv[1] -> "123";
?? ??? ??? ??? ??? ??? ?//argv[2] -> "456";
?? ??? ??? ??? ??? ??? ?//argv[3] -> "789";
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ?
?? ??? ??? ?練習:
?? ??? ??? ???? 1.? 請大家寫一個程序,將main函數的參數一個一個全部輸出,
?? ??? ??? ??? ???? 并且打印main的參數個數
?? ??? ??? ??? ?? int main(int argc,char **argv)
?? ??? ??? ??? ?? {
?? ??? ??? ??? ????? printf("argc==%d\n",argc);
?? ??? ??? ??? ??? ? int i;
?? ??? ??? ??? ??? ? for(i=0;i<argc;i++)
?? ??? ??? ??? ??? ? {
?? ??? ??? ??? ??? ???? printf("argv[%d]=>%s\n",i,argv[i]);
?? ??? ??? ??? ??? ? }
?? ??? ??? ??? ?? }
?? ??? ??? ??? ? ?
?? ??? ??? ?? 2.? 請各位大佬們,輸入兩個整型數據字符串,
?? ??? ??? ??? ?? 完成兩個整數相加
?? ??? ??? ??? ? ?
?? ??? ??? ??? ?? ./a.out 123 456
?? ??? ??? ??? ?? ==> 579
?? ??? ??? ??? ? ?
?? ??? ??? ??? ?? /*
?? ??? ??? ??? ?if(argc != 3)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?printf("Input error\n");
?? ??? ??? ??? ??? ?return 0;
?? ??? ??? ??? ?}

?? ??? ??? ??? ?int sum = atoi(argv[1]) + atoi(argv[2]);
?? ??? ??? ??? ?printf("sum == %d\n", sum);
?? ??? ??? ??? ?*/
?? ??? ??? ????

15.動態內存分配函數

??? main()
?? ?{
?? ??? int n;
?? ??? scanf("%d",&n);
?? ??? int a[n];? // 動態數組,根據用戶的輸入,數組元素的個數動態改變的。
?? ?????????????? //上述方法,在一些編譯器中可能不被認可
?? ??? ??? ??? ?? // 那么,咱們還有沒有其他的辦法呢?
?? ?}
?? ?
?? ?malloc/realloc/calloc
?? ?free
?? ?
?? ?NAME
?????? malloc, free, calloc, realloc - allocate and free dynamic memory

SYNOPSIS
?????? #include <stdlib.h>
???????????? malloc: 用來動態分配一個size大小的空間,并且把分配到內存空間的首地址返回。
?? ??? ??? ????????? malloc分配的空間的生存期,是隨進程持續性。malloc分配的空間一旦分配
?? ??? ??? ??? ??? ? 給你,它就不會自動釋放,一定要你自己去調用free 或 你的進程消亡了。
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ? void *malloc(size_t size);
???????????????????? @size:
?? ??? ??? ??? ??? ???????? 要分配的內存空間的大小
?? ??? ??? ??? ??? ?返回值:
?? ??? ??? ??? ??? ???????? 成功返回分配的內存空間的首地址
?? ??? ??? ??? ??? ??? ??? ?失敗返回NULL。
?? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ?例子:
?? ??? ??? ?????? 1.? int a[n];
?? ??? ??? ??? ????? //開辟了sizeof(int) * n 連續的內存空間
?? ??? ??? ??? ??? ? //現在相當于a數組名當作指針來看,a指向了n*sizeof(int)的連續的內存空間
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ? <=> int *a =(int *)malloc(n * "乘號" sizeof(int))
?? ??? ??? ??? ??? ??? // 現在a就相當于是有n個int類型元素的數組啦。
?? ??? ??? ??? ??? ??? // a就相當于數組名
?? ??? ??? ??? ??? ?? ?
?? ??? ??? ??? ?? 2. char *p = (char *)malloc(100);
?? ??? ??? ??? ???????? // p指向了一個100字節的內存空間
?? ??? ??? ??? ??? ??? ?// 通過p指針操作去訪問這段空間。
?? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?char ch;
?? ??? ??? ??? ??? ? p = &ch;
?? ??? ??? ??? ??? ???? // p指向ch,那么,上面100字節的空間就沒有任何指針指向它了
?? ??? ??? ??? ??? ??? ?//這100個字節的內存是不是就訪問不了,但是這段內存他是存在的。
?? ??? ??? ??? ??? ??? ?//并且也不能夠去分配給別人。。這樣的內存我們稱之為垃圾內存。
?? ??? ??? ??? ??? ??? ?// 把這樣的一種現象稱之為“內存泄露”
?? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ?malloc 可能會導致內存泄露(產生一些垃圾內存)
?? ??? ??? ??? ??? ??? ?比如說,上述的例子?? ?
?? ??? ????? ----------------------------------------------------
??????????????????? free:用來釋放ptr指向的內存的?? ?
???????????????????????? void free(void *ptr);?? ??? ?
??????????????????????? @ptr:必須是malloc/realloc/calloc 這三個函數申請的內存
????????????????????????????? 釋放后的這部分數據可能存在并且維持原來的值,也有可能被清空
????????????????????????????? 或者也有可能被修改為了其他的值。釋放之后,本質上來說,是不被
????????????????????????????? 允許去訪問那塊內存了,因為那塊內存不屬于你了,但是有些編譯器
????????????????????????????? 還是允許去訪問,但是呢訪問的結果是不確定的。
??????????????????????? so,建議大家? 將內存free掉了之后,立馬將那個內存的指針指向NULL。?? ?
????????????? ----------------------------------------------
??? calloc : 作用類似與malloc,也是用來分配動態內存空間的
???????????? 不過他是數組分配函數,既然是數組,那么這個函數帶有兩個參數

???????????? void *calloc(size_t nmemb, size_t size);
?? ??? ??? ?????? @nmemb : 表示分配多少個數組元素
?? ??? ??? ??? ?? @size :表示每一個元素占多少個字節
?? ??? ??? ??? ?? so,它總共分配的連續空間大小為:nmemb * size
?? ??? ??? ??? ? ?
?? ??? ??? ??? ?calloc(n,size) <==> malloc(n*size)
?? ??? ??? ??? ?
?? ??? ??? ?例子:
?? ??? ??? ??????? int a[10];
?? ??? ??? ??? ???????? ==> int *a = (int *) calloc (10,sizeof(int));
?? ??? ??? ??? ??? ??? ?==> int *a = (int*)malloc(10*sizeof(int));
?? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ?char ch[5];
?? ??? ??? ??? ??? ??? ==>char *ch =(char*)calloc(5,sizeof(char));
?? ??? ??? ??? ??? ??? ==>char *ch =(char*)malloc(5*sizeof(char));
?? ??? ??? ??? ?-----------------------------------------------
?? ?realloc: 用來把ptr指向的動態內存,拓展到size大小
?? ?????? void *realloc(void *ptr, size_t size); ?
??????????????? @ptr: 由malloc/realloc/calloc 返回的動態內存的地址
??????????????? @size: 將原來的空間,拓展到size大小

??????????????????? ptr = NULL ?
??????????????????????????? realloc(NULL,size) <=> malloc(size)
??????????????????? ptr != NULL
??????????????????????????? 拓展
?????????????????????????? 1.size 》 原來大小
?? ??? ??? ??? ??? ??? ??????????????? realloc 用來把ptr指向的內存,擴展到size字節,原來的內存內容保持不變,
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? 后面新增的內容不會初始化
?? ??? ??? ??? ??? ??? ??? ??? ??? ???? ?
?????????????????????????? 2.size == 0
?? ??? ??? ??? ??? ??? ???????????? realloc(ptr,0) <===> free(ptr)
?????????????????????????? 3.size < 原來大小?? ??? ??? ??? ??? ??? ?? ?
???????????????????????????????????? 這種情況,作者都沒有考慮,這種行為結果是未定義的(什么結果都可能會發生)
?? ??? ??? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ?練習: 咱們在一個函數中,值可以有哪些方式來傳遞?
?? ??? ??? ??? ??????? (1)對象的指針
?? ??? ??? ??? ??? ??? (2)通過函數的返回值
?? ??? ??? ??? ??? ??? (3)全局變量
?? ??? ??? ??? ??? ?? ?
?? ??? ??? ??? ???????? 請大家設計一個函數,分配指定的內存塊(100bytes)
?? ??? ??? ??? ??? ??? ?#include <stdio.h>
?? ??? ??? ??? ??? ??? ?char *q = NULL;
?? ??? ??? ??? ??? ??? ?void func_1(void)
?? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ????? q = (char*)malloc(100);
?? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ?int main()
?? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ???? char *p =NULL;
?? ??? ??? ??? ??? ??? ???? //調用func函數,目的是讓p指向100bytes的首地址
?? ??? ??? ??? ??? ??? ??? ?func_1();
?? ??? ??? ??? ??? ??? ??? ?p = q;
?? ??? ??? ??? ??? ??? ??? ?free(p);
?? ??? ??? ??? ??? ??? ?}

練習:
??????? 1.實現strncpy函數
??????? ?
?? ??? ? char * my_strncpy(char *dest ,const char *src , int n )
?? ??? ? {
?? ??? ??????? int i ;
?? ??? ??? ??? for(i=0;i<n&&src[i]!='\0';i++)
?? ??? ??? ??? {
?? ??? ??? ?????? dest[i] = src[i];
?? ??? ??? ??? }
?? ??? ??? ??? while(i<n)
?? ??? ??? ??? {
?? ??? ??? ??????? dest[i] = '\0';
?? ??? ??? ??? ??? i++;
?? ??? ??? ??? }
?? ??? ??? ??? return dest;
?? ??? ? }
?? ??? ?
??????? 2.實現strcmp函數
?? ??? ? #include <assert.h>
?? ??? ?
?? ??? ?int my_strcmp(const char * str1,const char * str2)
?? ??? ?{
?? ??? ????? //assert :斷言
?? ??? ???? assert(str1!=NULL && str2 != NULL);
?? ??? ??? ?int ret =0;
?? ??? ??? ?while(!(ret = *str1-*str2))
?? ??? ??? ?{
?? ??? ??? ????? str1++;
?? ??? ??? ??? ? str2++;
?? ??? ??? ?}
?? ??? ??? ?if(ret > 0)
?? ??? ??? ?{
?? ??? ??? ???? ret = 1;
?? ??? ??? ?}
?? ??? ??? ?else if(ret<0)
?? ??? ??? ?{
?? ??? ??? ???? ret = -1;
?? ??? ??? ?}
?? ??? ??? ?return ret;
?? ??? ??? ?
?? ??? ?}

??????? 3.n個人圍成一圈,編號從1到n,從編號為1的人開始報數,報到m的人離隊,
????????? 下面的人接著從1開始報數,依次下去,寫程序求最后剩下一個人的編號!
??????????? /*
?? ??? ??? ????? Baoliu_num : 剩下的一個人的編號是幾
?? ??? ??? ??? ? @a : 數組名
?? ??? ??? ??? ? @n : n個人
?? ??? ??? ??? ? @m : 報道m離隊
?? ??? ??? ??? ? 返回值:??? 返回剩下的那一個人的編號
?? ??? ??? ?*/
??????????? int Baoliu_num(int *a,int n,int m)
?? ??? ??? ?{
?? ??? ??? ????? int out= 0;?? //記錄已經離隊多少
?? ??? ??? ??? ?
?? ??? ??? ??? ? int count = 0; // 記錄當前的報數
?? ??? ??? ??? ? int i;
?? ??? ??? ??? ? int *p = a;
?? ??? ??? ??? ? for(i = 0;i<n;i++)
?? ??? ??? ??? ? {
?? ??? ??? ??? ????? *(p+i) = i+1;
?? ??? ??? ??? ? }
?? ??? ??? ??? ? i = 0; //i為目前報道第幾人
?? ??? ??? ??? ? while(out<n-1)
?? ??? ??? ??? ? {
?? ??? ??? ??? ????? if(*(p+i)!=0)
?? ??? ??? ??? ??? ? {
?? ??? ??? ??? ??? ???? count ++;
?? ??? ??? ??? ??? ? }
?? ??? ??? ??? ??? ? if (count == m)
?? ??? ??? ??? ??? ? {
?? ??? ??? ??? ??? ????? coun t =0;
?? ??? ??? ??? ??? ??? ? *(p+i) = 0;
?? ??? ??? ??? ??? ??? ? out++;
?? ??? ??? ??? ??? ? }
?? ??? ??? ??? ??? ? i++;
?? ??? ??? ??? ??? ? if(i==n)
?? ??? ??? ??? ??? ? {
?? ??? ??? ??? ??? ???? i = 0;
?? ??? ??? ??? ??? ? }
?? ??? ??? ??? ? }
?? ??? ??? ??? ? for(i=0;i<n;i++)
?? ??? ??? ??? ? {
?? ??? ??? ??? ???? if(*(p+i)!=0)
?? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? printf("%d\n",*(p+i));
?? ??? ??? ??? ??? ??? break;
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ? }
?? ??? ??? ?}
?? ??? ??? ?
??????? 4. 分析如下代碼是否正確,為什么?
?? ??? ?
?? ??? ?(1)
?? ??? ??? ?int? main()
?? ??? ??? ?{
?? ??? ??? ??? ?char a;
?? ??? ??? ??? ?char * str = &a;
?? ??? ??? ??? ?strcpy(str, "hello");
?? ??? ??? ??? ?printf("%s\n", str);
?? ??? ??? ??? ?
?? ??? ??? ??? ?return 0;
?? ??? ??? ?}
??????????? 錯誤的,在調用strcpy的時候,出現了越界,一旦越界就可能導致段錯誤
?? ??? ??? ?造成”段錯誤“,后面的程序就不會被執行,沒有輸出結果。
??????? (2)
?? ??? ??? ?char * GetMemory(void)
?? ??? ??? ?{
?? ??? ??? ??? ?char p[] = "hello world";
?? ??? ??? ??? ?
?? ??? ??? ??? ?return p;
?? ??? ??? ?}
?? ??? ??? ?? ?
?? ??? ??? ?int main()
?? ??? ??? ?{
?? ??? ??? ??? ?char * str = NULL;
?? ??? ??? ??? ?str = GetMemory();
?? ??? ??? ??? ?printf("%s\n", str); //
?? ??? ??? ?}
?? ??? ??? ?
??????????? 編譯錯誤:數組是不能進行返回
?? ??? ??? ?返回的是指向”棧空間“的指針,函數結束,棧空間內存已經被收回,
?? ??? ??? ?那么那塊內存可能就不能夠被訪問了,而且內存的內容是不可知的。
?? ??? ??? ?

??????? (3)
?? ??? ??? ?char * s = "AAA";
?? ??? ??? ?printf("%s", s);
?? ??? ??? ?s[0] = 'B';
?? ??? ??? ?printf("%s", s);
?? ??? ??? ?
?? ??? ??? ?因為”s[0]='B'“,s指向的是一個 .rodata的只讀空間
?? ??? ??? ?不能進行寫的操作
?? ??? ??? ?

??????? (4)
?? ??? ??? ?swap(int * p1 , int * p2)
?? ??? ??? ?{
?? ??? ??? ??? ?int * p ;
?? ??? ??? ??? ?*p = *p1;
?? ??? ??? ??? ?*p1 = *p2;
?? ??? ??? ??? ?*p2 = *p;
?? ??? ??? ?}
?? ??? ??? ?p是一個野指針,后面的操作都是在操作野指針,
?? ??? ??? ?操作野指針,可能會導致內存的非法訪問,出現段錯誤

?????????? (5)

下列程序的輸出結果是?(5)

int main()

{

char a[10]={9,8,7,6,5,4,3,2,1,0},*p=a+5;

printf("%d",*--p);

}

(6)下列程序的運行結果是?? (3? 6)

void fun(int *a,int *b)

{

int *k;

k=a;

a=b;

b=k;

}

int main()

{
int a=3,b=6,*x=&a,*y=&b;

fun(x,y);

printf("%d %d",a,b,);

}

(7)以下程序的輸出結果是?(7)

#include <stdio.h>

#include<string.h>

main()

{

char b1[8]="abcdefg",b2[8],*pb=b1+3;

while(--pb>=b1)

strcpy(b2,pb);

int? l=strlen(b2);

pritntf("%d\n",strlen(b2));

}

(8)若有一些定義和語句,錯誤的是?? (A)

#include <stdio.h>

int a=4,b=3,*p,*q,*w;

p=&a;q=&b;w=q;q=NULL

A,*q=0?? B,w=p; C,*p=a D,*p=*w;

(9)以下程序的輸出結果是?? (空格)

int main()

{

char *p="abcdefgh",*r;

long *q;

q=(long*)p;

q++;

r=(char*)q;

printf("%s\n",r);

}

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

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

相關文章

藍橋樓賽第30期-Python-第三天賽題 統計學習數據題解

樓賽 第30期 Python 模塊大比拼 統計學習數據 介紹 JSON&#xff08;JavaScript Object Notation, /?d?e?s?n/&#xff09;是一種輕量級的數據交換格式&#xff0c;最初是作為 JavaScript 的子集被發明的&#xff0c;但目前已獨立于編程語言之外&#xff0c;成為了通用的…

分享10個國內可以使用的GPT中文網站

在今天的人工智能領域&#xff0c;基于對話的語言模型已成為研究的熱點&#xff0c;尤其是像 ChatGPT 這樣因其出色的語言理解與對話交互能力而廣受關注的模型。本文將介紹10個國內可以直接使用GPT的網站&#xff0c;旨在為大家在選擇和使用這些優秀的AI工具時提供有價值的參考…

使用pyqt繪制一個愛心!

使用pyqt繪制一個愛心&#xff01; 介紹效果代碼 介紹 使用pyqt繪制一個愛心&#xff01; 效果 代碼 import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget from PyQt5.QtGui import QPainter, QPen, QBrush, QColor from PyQt5.QtCore import Qt, Q…

[保姆式教程]使用目標檢測模型YOLO V8 OBB進行旋轉目標的檢測:訓練自己的數據集(基于衛星和無人機的農業大棚數據集)

最近需要做基于衛星和無人機的農業大棚的旋轉目標檢測&#xff0c;基于YOLO V8 OBB的原因是因為嘗試的第二個模型就是YOLO V8&#xff0c;后面會基于YOLO V9模型做農業大棚的旋轉目標檢測。YOLO V9目前還不能進行旋轉目標的檢測&#xff0c;需要修改代碼 PS:歡迎大家分享農業大…

【研發日記】Matlab/Simulink技能解鎖(九)——基于嵌入式處理器仿真

文章目錄 前言 基于嵌入式處理器仿真 使用方式 第一步&#xff0c;硬件連接 第二步&#xff0c;配置硬件資源 第三步&#xff0c;配置XCP協議 第四步&#xff0c;加載Contrl Model 第五步&#xff0c;運行仿真 第六步&#xff0c;仿真報告 分析和應用 總結 參考資料 前言…

無線技術整合到主動噪聲控制(ANC)增強噪聲降低性能

主動噪聲控制&#xff08;ANC&#xff09;已成為一種廣泛使用的降噪技術。基本原理是通過產生與外界噪音相等的反向聲波&#xff0c;將噪音中和&#xff0c;從而達到降噪的效果。ANC系統通常包括以下幾個部分&#xff1a;參考麥克風、處理芯片、揚聲器和誤差麥克風。參考麥克風…

家政保潔服務小程序怎么做?家政公司快速搭建專屬小程序

在數字化時代背景下&#xff0c;家政保潔服務行業也迎來了線上轉型的新機遇。家政保潔服務小程序&#xff0c;作為一種新型的線上服務平臺&#xff0c;不僅能夠提升家政公司的服務效率&#xff0c;還能為顧客提供更加便捷的預約上門服務體驗。那么家政保潔服務小程序怎么做呢&a…

AI與量子計算:科技新時代的雙重飛躍

在科技的浪潮中,每一次技術革新都如同一次深海潛行,探尋著未知的奧秘。近年來,人工智能(AI)和量子計算兩大領域的發展尤為引人注目,它們不僅代表了科技的未來趨勢,更是人類社會進步的強大動力。本文將深入探討這兩項技術的最新進展、潛在影響以及它們之間的潛在聯系。 …

2024年3月小程序類目調整匯總公告

各位小程序開發者&#xff1a; 為進一步加強平臺的規范管理&#xff0c;優化開發者類目選擇體驗&#xff0c;現對以下類目進行調整&#xff0c;請各位開發者知悉。 類目調整 #【文娛-小說】 現資質要求 &#xff08;3選1&#xff09;&#xff1a; 1、提供《互聯網出版許可…

從零開始搭建一個SpringBoot項目

目錄 Spring BootSpring Boot 項目開發環境1、快速創建SpringBoot項目2、pom.xml 添加 Meavn 依賴3、配置application.yml4、驗證數據庫是否連接成功5、配置 Druid 數據源 Spring Boot 整合 MyBatis1、準備依賴2、application-dev.yml 配置3、啟動類添加Mapper接口掃描器4、設置…

BWVS 靶場測試

一、PHP弱類型 is_numeric() 輸入&#xff1a;127.0.0.1/BWVS/bug/php/code.php # 1、源代碼分析 如果num不是數字&#xff0c;那么就輸出num&#xff0c;同時如果num1&#xff0c;就輸出flag。即num要是字符串又要是數字 # 2、函數分析&#xff1a; is_numeric()函數&…

使用Nginx的Mirror模塊的指南

Nginx 是一個廣泛使用的 web 服務器和反向代理服務器&#xff0c;性能出色且易于配置。Nginx 提供了各種模塊來擴展其功能&#xff0c;其中一個有用的模塊是 mirror 模塊。本文將詳細介紹 Nginx 的 mirror 模塊&#xff0c;包括其用途、使用場景、注意事項以及示例代碼。 1. m…

《最新出爐》系列入門篇-Python+Playwright自動化測試-40-錄制生成腳本

宏哥微信粉絲群&#xff1a;https://bbs.csdn.net/topics/618423372 有興趣的可以掃碼加入 1.簡介 各種自動化框架都會有腳本錄制功能&#xff0c; playwright這么牛叉當然也不例外。很早之前的selenium、Jmeter工具&#xff0c;發展到每種瀏覽器都有對應的錄制插件。今天我們…

牛客NC392 參加會議的最大數目【中等 貪心+小頂堆 Java/Go/PHP 力扣1353】

題目 題目鏈接&#xff1a; https://www.nowcoder.com/practice/4d3151698e33454f98bce1284e553651 https://leetcode.cn/problems/maximum-number-of-events-that-can-be-attended/description/ 思路 貪心優先級隊列Java代碼 import java.util.*;public class Solution {/**…

java面試高級篇(JVM、Mysql、Redis、Kafka)

文章目錄 面試專題-java高級篇1. JVM有做過jvm的調優嗎?常用的jvm參數調優有哪些?如果jvm持續一段時間頻繁的發生Young GC (輕GC) 可能原因有哪些? 2. Mysql2.1. 基本功(見為知筆記)2.2. 什么是索引2.3. 索引的優劣勢2.4. MySQL的索引結構2.4.1. B-Tree索引2.4.2. BTree索引…

外賣系統源碼開發全攻略:外賣小程序與后臺管理系統的設計與實現

今天&#xff0c;小編將詳細介紹外賣系統源碼的開發全攻略&#xff0c;從需求分析到設計與實現&#xff0c;為開發者提供全面指導。 一、需求分析 1.用戶需求 用戶是外賣系統的核心&#xff0c;需滿足以下基本需求&#xff1a; -瀏覽菜單并下單 -實時追蹤訂單 -多種支付方…

每日一題——博弈論(枚舉與暴力)

博弈論 題目描述 運行代碼 #include<iostream> #include<vector> using namespace std; int main(){int n;cin >> n;vector<int> d(n,0);for(int i 0;i < n;i){cin >> d[i];}vector<int> in(1000,0);for(int k 1;k<3;k){for(int…

ESP32燒錄AT固件并進行MQTT通訊

首先下載AT固件 發布的固件 - ESP32 - — ESP-AT 用戶指南 latest 文檔 下載燒錄工具 下載指導 - ESP32 - — ESP-AT 用戶指南 latest 文檔 燒錄后注意usb的串口是不能發AT指令的 需要用16和17腳 用AT指令確認OK后連WIFI ATCWMODE1 //設置客戶端模式 ATCWLAP …

mysql誤刪后使用binlog恢復數據

1 預期效果 使用 binlog 恢復數據的預期效果是將誤刪的數據還原到誤刪之前的狀態&#xff0c;以減少或消除數據丟失的影響。通過正確解析和執行 binlog 中的操作記錄&#xff0c;可以重新執行誤刪操作之后的插入、更新或刪除操作&#xff0c;從而恢復被誤刪的數據。 數據恢復&…

Cocos Creator 編輯器的數據綁定詳解

Cocos Creator 是一款由 Cocos 平臺推出的游戲開發工具&#xff0c;它集成了圖形化編輯器、腳本引擎和資源管理器等功能&#xff0c;方便開發者快速地創建游戲。其中&#xff0c;數據綁定是 Cocos Creator 編輯器中非常重要的一個功能&#xff0c;它可以幫助開發者實現頁面元素…