C語(yǔ)言-指針類型

  • 改值場(chǎng)景示例
- 改變 n 的值 的函數(shù)
void change(int n)
{
  n = 10;
}

int main()
{
  int a = 20;

  - 這里只能把 變量a 的值傳到 change() 函數(shù)里面去
  change(a);
  - 如果想要修改 變量a 的值, 就不能只單單將 變量a 的值傳過(guò)去
  - 而是將 變量a 的地址傳過(guò)去 
  - &:取地址符  :)
  - 但是 change() 函數(shù) 不支持傳地址,只能接受 int 類型的值
  - 只有指針變量 才能接收地址
  - 利用指針變量,接收地址,根據(jù) 地址 找到 變量a 的存儲(chǔ)空間,把它的值改掉

  printf("a = %d \n",a);

  return 0;
}

指針就一個(gè)作用:能夠根據(jù)一個(gè)地址值,訪問(wèn)對(duì)應(yīng)的存儲(chǔ)空間

  • 定義指針變量 [作用:取值 和 賦值]
    • 指針變量: 只能存儲(chǔ) 地址
    • 指針變量 占據(jù) 8 個(gè)字節(jié)
    • *:指針運(yùn)算符
      • 定義 指針變量 時(shí):僅僅是一個(gè)象征,代表定義一個(gè) 指針變量
      • 賦值時(shí):代表訪問(wèn) 指針變量 指向的 存儲(chǔ)空間
- 格式:變量類型 *變量名;
- '*':指針變量的標(biāo)識(shí)

- 定義一個(gè)整型變量
int a;

- 定義一個(gè) int *p;
- 這個(gè)時(shí)候的 '*' 是個(gè)象征,代表這個(gè)類型是個(gè)指針
- 可以看做 'int *' 是一起的 // 強(qiáng)調(diào)
int *p; *英文名 point  指針
- 指針變量只能存儲(chǔ)地址

a = 30;

- 這樣寫 不合理, 指針變量p 只能存儲(chǔ)地址,變量a 把值 30 給 指針變量p
p = a; 

- 把 變量a 的地址給了 指針變量p
- &:取地址符 :)
- 專業(yè)術(shù)語(yǔ):指針變量p 指向了 變量a
p = &a;

- 訪問(wèn) 指針變量p 指向的 存儲(chǔ)空間
*p

- 這個(gè)時(shí)候的 '*' 代表訪問(wèn) 指針變量p 指向的 存儲(chǔ)空間 // 強(qiáng)調(diào)
- 把 10 賦值給 指針變量p 指向的 存儲(chǔ)空間
*p = 10;
- 這句代碼,利用 *p 訪問(wèn)了 指針變量p 指向的 存儲(chǔ)空間
- 然后把 10 賦值給 *p 找到的這塊存儲(chǔ)空間
- 就把 變量a 的值 改為了 10;

printf("a = %d \n",a); // 輸出 是 a = 10

- 改 變量a 的值,打印 *p 的值
a = 30;
printf("%d \n", *p); // 輸出 是 30

- 指向 char 類型
char c = 'A';
char *cp = &c;
*cp = 'D';
printf("%c \n", *cp); // 輸出 是 D
printf("%c \n", *c); // 輸出 是 D

指針 注意點(diǎn)

*p = 10;
- 這樣寫 就是 賦值

- 這樣寫 就是 取值
printf("%d \n", *p); 

- 這個(gè) 指針變量p  只能指向 整型類型的變量
int *p;

- 這個(gè) 指針變量p  只能指向 double類型 的變量 
double *p;

- 不建議的寫法,int *p 只能指向 int類型 的數(shù)據(jù)
int *p;
double d = 10.0;
p = &d;
- 不建議的寫法

- 指針變量只能存儲(chǔ)地址
int *p;
p = 200;
- 錯(cuò)誤寫法

- 指針變量未經(jīng)過(guò)初始化,不要拿來(lái)間接訪問(wèn)其他存儲(chǔ)空間
int *p;
printf("%d \n", *p);
- 錯(cuò)誤寫法

- 錯(cuò)誤寫法
*p = &a;
- 錯(cuò)誤寫法

- 可以這樣直接定義時(shí)訪問(wèn)
int *p = &a;

指針定義時(shí) 為什么要 指定類型

  • 就是為了 取值、賦值
  • 不指定,就會(huì) 數(shù)據(jù)錯(cuò)亂
  • 用什么樣的 類型 定義指針,那么用指針訪問(wèn)變量存儲(chǔ)空間時(shí),就會(huì)取值這個(gè)類型相應(yīng)的字節(jié)數(shù)據(jù)
  • 一字節(jié)等于八位 :)
- 例如,定義一個(gè) int 類型的 變量a,和一個(gè) char 類型的 變量c,并賦初始值
int a = 2; // 0000 0000 0000 0000 0000 0000 0000 0010 // 二進(jìn)制 4個(gè)字節(jié)
- int 占據(jù) 4 個(gè)字節(jié),一字節(jié)等于八位, 二進(jìn)制就是 4 * 8 = 32 位

char c = 1; // 0000 0001 // 二進(jìn)制 1個(gè)字節(jié)
- char 占據(jù) 1 個(gè)字節(jié),一字節(jié)等于八位, 二進(jìn)制就是 1 * 8 = 8 位

- 變量a 在內(nèi)存中的存儲(chǔ)占4個(gè)字節(jié),變量c 占1個(gè)字節(jié)
- 在內(nèi)存中是這樣排布的,存儲(chǔ)的數(shù)據(jù)是 二進(jìn)制
- 先定義的 變量,其存儲(chǔ)空間優(yōu)先分配,且在最下方
- 一行代表 一個(gè)字節(jié)

- 如果 定義 int 類型 的指針變量 取 變量c 的值
int *p = &c;

c 0000 0001 // 取到這里
a 0000 0010
  0000 0000
  0000 0000 // 從這里開始取值
  0000 0000

- 那么就是從 變量c 的存儲(chǔ)地址處,取 8 個(gè)字節(jié)的數(shù)據(jù)
- 從下往上取值,先進(jìn)后出,按 二進(jìn)制 的書寫格式,取出來(lái)就是這樣的數(shù)據(jù)
- 二進(jìn)制:0000 0000 0000 0000 0000 0010 0000 0001
- 換算成十進(jìn)制:513;

printf(" *p %d \n", *p); // 輸出是 513
printf("  c %d \n", c); // 輸出是 1

- 所以 指針定義 為什么要指定類型
- 就是為了 `取值`、`賦值`
- 不指定,就會(huì) 數(shù)據(jù)錯(cuò)亂
  • 重新實(shí)現(xiàn) 開頭 改值場(chǎng)景示例
void change(int *n)
{
  *n = 10;
}

int main()
{
  int a = 20;

  change(&a);
  printf("a = %d \n",a); // 輸出 是 a = 10

  return 0;
}

指向指針的指針,以此類推,基本不常見

int a = 10;
int *p = &a;
(int *) *pp = &p;

- 修改 變量a 的值 
1. a = 20;
2. *p = 20;

- 這里是 '==' 表示 左右 是一樣的 相同的
3. *pp == p;
*(*pp) == *p = a;
**pp == *p = a;
- 這里是 '==' 表示 左右 是一樣的 相同的

- 修改 指針變量p 指向的 變量a 的值 20
**pp = 20;

 printf("a = %d \n",a); // 輸出 是 a = 20
指向指針的指針.png

輸出格式符

輸出格式符.png

指針與數(shù)組

  • 數(shù)組名就是 數(shù)組的 地址,也是 數(shù)組 首元素 的地址
int nums[5] = {11, 25, 3, 94, 5};

nums[0]; - 訪問(wèn) 首元素
&nums[0]; - 取出 首元素的 地址

- 定義一個(gè) int 類型的 指針變量p
int *p;
- 指針變量p 指向了數(shù)組的首元素
p = &nums[0];

- 數(shù)組名 就是 數(shù)組的 地址,也是數(shù)組 首元素 的地址
- 可以 直接賦值給 指針變量p
p = ages;
printf(" %d \n",*p); // 輸出 是 11

- 現(xiàn)在 指針變量p 存儲(chǔ)的是 nums 數(shù)組首元素 的地址
- 指針變量的 +1 表示,(p + 1)指向 nums 數(shù)組 第二個(gè)元素 的地址,地址值 +4 
- 并不是 地址值 +1,而是取決于 指針的類型,int 占據(jù) 4 個(gè)字節(jié)
p + 1;

/* + 0 可以不寫,為了 看著舒服 :)
p + 0 ---> &nums[0] 
p + 1 ---> &nums[1] 
p + 2 ---> &nums[2] 
p + i ---> &nums[i] 
*/

printf(" %p \n",p);
printf(" %p \n",p+1);
printf(" %p \n",p+2);

- 這就意味著,可以通過(guò) 指針變量p,間接算出數(shù)組后面元素的地址,取出相應(yīng)的值

printf(" %d \n",*(p + 1)); // 輸出 是 25
printf(" %d \n",*(p + 2)); // 輸出 是 3

- 利用指針 遍歷數(shù)組的值
for (int i = 0;i < 5; i++){
  printf(" nums[%d] = %d \n", i, *(p + i));
}

- 還可以把 指針當(dāng)做 數(shù)組來(lái)用
- 因?yàn)榘?數(shù)組地址 給了 指針變量p
- 相當(dāng)于把 數(shù)組名 給了 指針變量p
printf(" %d \n",p[2])); // 輸出 是 3 

  • 數(shù)組元素的 訪問(wèn)方式
    1 > 數(shù)組名[下標(biāo)] nums[i]
    2 > 指針變量名[下標(biāo)] p[i]
    3 > *(p + i)

  • 指針變量的 +1,地址值 究竟加多少,取決于 指針的類型
    1 > int * 4
    2 > char * 1
    3 > double * 8

指針與字符串

  • C語(yǔ)言的內(nèi)存 分為 3 大塊
    • 常量區(qū):存放一些常量字符串(里面東西不能改)
    • :存放對(duì)象
    • :存放局部變量(C語(yǔ)言數(shù)組放在棧里面)
- 這種 字符串 寫法,容易被修改
- 稱之為:字符串 變量 // 
char name[] = "june";
name[0] = 'J';

printf(" %s \n", name); // 輸出 是 June

- 稱之為:字符串 常量 // 
- "June" == 'J' + 'u' + 'n' + 'e' + '\0'
char *name2 = "June";
- 指針變量name2 指向了 字符串的 首字符

printf(" %c \n", *name2); // 輸出 是 J

- 這樣不可修改
*name2 = 'J';
printf(" %s \n", name2); // 程序崩潰  :)

char *name3 = "June";
printf(" %p %p \n", name2, name3); //  輸出 地址相同
- 說(shuō)明 name2 和 name3 都放在 常量區(qū)
- 它們指向的 字符 是 同一個(gè)字符
  • 總結(jié):定義字符串的 2 種方式
1. 利用數(shù)組:char name[] = "June";
- 特點(diǎn):字符串里面的字符是可以修改的
- 使用場(chǎng)合:字符串內(nèi)容需要經(jīng)常修改

2. 利用指針:char *name = "June";
- 特點(diǎn):字符串其實(shí)是一個(gè)常量字符串,里面的字符不能修改
- 使用場(chǎng)合:字符串內(nèi)容不需要修改,而且這個(gè)字符串經(jīng)常使用

** 頻繁的開辟存儲(chǔ)空間和銷毀,非常消耗性能   **

指針數(shù)組

- 整型數(shù)組
int ags[3];

- 指針數(shù)組(字符串?dāng)?shù)組):里面存放的都是指針,每個(gè)指針都有自己指向的字符
char *names[3] = {"Vampire", "June", "VampireJune"};

- 二維字符數(shù)組(字符串?dāng)?shù)組)
char name2[2][10] = {"Vampire", "June"};

字符串 輸入

char name[20];
print("請(qǐng)輸入姓名:\n");

- 數(shù)組名 就是數(shù)組的 地址
scanf("%s", name); - 輸入 June

- scanf 本質(zhì)
- 從 name 的地址開始,一個(gè)一個(gè)存放輸入的字符,并且會(huì)在最后補(bǔ)上一個(gè) '\0'

- 'J' 'u' 'n' 'e' '\0'
print("剛剛輸入姓名:%s \n", name); - 輸出 June

print("%c \n", name[3]); - 輸出 e

返回 指針 的 函數(shù)

- 返回 char 類型 的數(shù)據(jù)
char june()
{
  return 'J';
}

- 返回 char * 類型的 數(shù)據(jù)
- 返回 指針的 函數(shù)
char *vampire()
{
  return "vampire";
}

int main()
{
  char *name = vampire()
  print("name = %s \n", name); - 輸出 vampire

  return 0;
}

指向 函數(shù) 的 指針

  • 函數(shù) 也有自己的 內(nèi)存地址
  • 函數(shù)名 就是 函數(shù)的 內(nèi)存地址
- vampire 函數(shù) 有自己的 內(nèi)存地址
void vampire()
{
  printf("調(diào)用了vampire函數(shù) \n");
}

- main 函數(shù) 有自己的內(nèi)存地址
int main()
{
  - (*p):固定寫法
  - 代表 指針變量p 將來(lái)肯定指向 函數(shù)
  - 左邊的 void:代表 指針變量p 指向的函數(shù) 沒(méi)有返回值
  - 右邊的():代表 指針變量p 指向的函數(shù) 沒(méi)有形參
  void (*p)();  

  - p 等于 函數(shù)的地址;
  - 指針變量p 指向了 vampire 函數(shù)
  p = vampire;

  - 直接調(diào)用函數(shù)
  p();

  - 取出 并 調(diào)用 vampire 函數(shù) 
  - 利用 指針變量 間接調(diào)用 函數(shù)
  (*p)();

  - 直接調(diào)用 函數(shù)
  vampire();

  return 0;
}
  • 進(jìn)階 - 指向 函數(shù) 的 指針
int sum(int vampire, int june)
{
  return vampire + june;
}

int main()
{
  - 定義 指針變量p 指向 sum 函數(shù)
  - 左邊的 int:代表 指針變量p 指向的函數(shù)返回 int 類型的數(shù)據(jù)
  - 右邊的(int, int):代表 指針變量p 指向的函數(shù)有 2 個(gè) int 類型的形參
  int (*p)(int, int);  

  p = sum;

  - 3 種函數(shù)調(diào)用方式
  int v = p(10, 11);
  int v = (*p)(10, 11);
  int v = sum(10, 11);
  printf("v = %d \n",v); - 輸出 21

   return 0;
}

double vampireJune(double d, char *s, int b)
{

}

- 定義指向 vampireJune 函數(shù)的 指針
double(*p1)(double, char *, int) = vampireJune;

- 調(diào)用
double v = vampireJune(2.3, "Vampire", 10);
double va = (*p1)(2.3, "June", 10);
double vam = p1(2.3, "VampireJune", 10);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 指針是C語(yǔ)言中廣泛使用的一種數(shù)據(jù)類型。 運(yùn)用指針編程是C語(yǔ)言最主要的風(fēng)格之一。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu); ...
    朱森閱讀 3,614評(píng)論 3 44
  • 第十章 指針 1. 地址指針的基本概念: 在計(jì)算機(jī)中,所有的數(shù)據(jù)都是存放在存儲(chǔ)器中的。一般把存儲(chǔ)器中的一個(gè)字節(jié)稱為...
    堅(jiān)持到底v2閱讀 1,166評(píng)論 2 3
  • 昨天整理材料時(shí),為了能夠早點(diǎn)回家休息,便囫圇吞棗式完成了一篇匯報(bào),9000字,19頁(yè)。批示完,漏了一段,文中...
    星辰羽凡閱讀 455評(píng)論 0 0
  • 我一個(gè)人待孩子三年,頭一年因?yàn)槭浅鯙槿四覆粫?huì)帶孩子,媽媽幫忙帶著,第二年讓婆婆過(guò)來(lái)幫忙帶,婆婆直說(shuō)要領(lǐng)會(huì)農(nóng)...
    竹中簡(jiǎn)閱讀 255評(píng)論 0 0
  • 問(wèn)題描述Given an array of integers, return indices of the two...
    前端伊始閱讀 151評(píng)論 1 0

友情鏈接更多精彩內(nèi)容