C語(yǔ)言由淺入深理解指針
1. 相關(guān)概念
- 操作系統(tǒng)給每個(gè)存儲(chǔ)單元分配了一個(gè)編號(hào),從ox00 00 00 00~0xff ff ff ff,這個(gè)編號(hào)稱為地址,指針就是地址
- 指針變量:即這個(gè)變量用來(lái)存放一個(gè)地址編號(hào)
- 無(wú)論什么類型的地址,都是存儲(chǔ)單元的變換,在32位平臺(tái)下都是4個(gè)字節(jié),即任何類型的指針變量都是4個(gè)字節(jié)大小,64位操作系統(tǒng)占8個(gè)字節(jié)。
- 對(duì)應(yīng)類型的指針變量,只能存放對(duì)應(yīng)類型的地址。例如整型指針變量,只能存放整型變量的地址。
#include <stdio.h> int main() { char *a; short *b; int *c; long *d; float *e; double *f; printf("sizeof(a)=%d\n", sizeof(a)); printf("sizeof(b)=%d\n", sizeof(b)); printf("sizeof(c)=%d\n", sizeof(c)); printf("sizeof(d)=%d\n", sizeof(d)); printf("sizeof(e)=%d\n", sizeof(e)); printf("sizeof(f)=%d\n", sizeof(f)); return 0; }
可見(jiàn),我的操作系統(tǒng)是64位的。
為什么在64位系統(tǒng)中指針的大小是8,而32位的卻是4?
64位系統(tǒng),這個(gè)位數(shù)指的是CPU 里面的通用寄存器的數(shù)據(jù)寬度為64位,也就是說(shuō)一個(gè)地址占二進(jìn)制位數(shù)是64,所以:
sizeof(double *)==sizeof(int *)==sizeof(char *)==64/8==8
32位系統(tǒng),同理,他的一個(gè)地址占32位二進(jìn)制空間,sizeof(double *)==sizeof(int *)==sizeof(char *)==32/8==4
其實(shí)明白了兩個(gè)系統(tǒng)的尋址原理就能明白,大體就是這個(gè)原因。地址跟系統(tǒng)有關(guān),但是基本數(shù)據(jù)類型占的大小是由C語(yǔ)言本身決定。
2. 指針的定義方法
數(shù)據(jù)類型 *指針變量名
int p; // 定義了一個(gè)指針變量p 在定義指針變量的時(shí)候, 是用來(lái)修飾變量的,代表指針變量。
關(guān)于指針的運(yùn)算符:
& 取地址 * 取值
#include <stdio.h> int main() { int a = 100; int *p; // 定義一個(gè)指針變量 p = &a; // 給指針變量賦值 printf("a = %d, %d\n", a, *p); // *p 等價(jià)于變量 a return 0; }
拓展:如果一行中定義多個(gè)指針變量,每個(gè)變量前面都要加*修飾
3. 指針的分類
- 字符指針
- 短整型指針
- 整型指針
- 長(zhǎng)整型指針
- float型指針
- double型指針
- 函數(shù)指針
- 結(jié)構(gòu)體指針
- 指針的指針
- 數(shù)組的指針
4. 指針和變量的關(guān)系
引用變量的方法:
1.直接通過(guò)變量的名稱
2.通過(guò)*指針名稱 引用
#include <stdio.h> int main() { int *p1, *p2, temp, a, b; p1 = &a; p2 = &b; printf("請(qǐng)輸入a,b的值:\n"); scanf("%d %d", p1, p2); // 和之前的scanf不同,這里直接用p1p2作為寫(xiě)入地址。 temp = *p1; // 用p1指向的變量a給temp賦值 *p1 = *p2; // 用p2指向的變量b給p1指向的變量a賦值 *p2 = temp; // temp給p2指向的變量b賦值 printf("a=%d b=%d\n", a, b); printf("*p1=%d,*p2=%d\n", *p1, *p2); return 0; }
如果想讓不同類型的指針相互賦值的時(shí)候,需要強(qiáng)制類型轉(zhuǎn)換:
#include <stdio.h> int main() { int a = 0x1234, b = 0x5678; // 4個(gè)字節(jié) char *p1, *p2; // char類型只能保存一個(gè)字節(jié) printf("%#x %#x\n", a, b); p1 = (char *)&a; // 強(qiáng)制類型轉(zhuǎn)換 p2 = (char *)&b; printf("%#x %#x\n", *p1, *p2); p1++; // 指針向上移動(dòng) p2++; printf("%#x %#x\n", *p1, *p2); return 0; }
5. 指針與數(shù)組的關(guān)系
指針保存的是數(shù)組第一個(gè)元素的地址
也可以通過(guò)*(p+2)=100給當(dāng)前地址的下一個(gè)變量賦值
#include<stdio.h> int main(){ int a[5] = {0,1,2,3,4}; int *p; p = a; // 指針指向數(shù)組a的第一個(gè)元素的首地址 printf("a[2]=%d\n",a[2]); printf("p[2]=%d\n",p[2]); // *(a+n) <==> *(p+n) <==> a[n] <==> p[n] printf("*(p+2)%d\n",*(p+2)); printf("*(a+2)%d\n",*(a+2)); printf("p=%p\n",p); printf("p+2=%p\n",p+2); return 0; }
6. 指針的運(yùn)算
指針可以加一個(gè)整數(shù),往下指幾個(gè)它指向的變量,結(jié)果還是地址
#include <stdio.h> void test1() { int a[10]; int *p, *q; p = a; q = p + 2; // p q 間隔8個(gè)字節(jié),意味著加一個(gè)整數(shù)最終移動(dòng)的字節(jié)數(shù)與指針變量的類型也有關(guān)系 printf("p=%p\n", p); printf("q=%p\n", q); return; } int main() { test1(); return 0; }
- 兩個(gè)相同的指針可以比較大小
前提:指向同一個(gè)數(shù)組的元素
#include <stdio.h> void test2() { int a[10]; int *p, *q; p = &a[1]; q = &a[6]; if (p < q) { printf("p < q\n"); } else if (p > q) { printf("p > q\n"); } else { printf("p = q\n"); } return; } int main() { // test1(); test2(); return 0; }
- 兩個(gè)同類型的指針可以做減法
前提:指向同一個(gè)數(shù)組元素,減法的結(jié)果是指針指向的中間有多少個(gè)元素
#include <stdio.h> void test3() { int a[10]; int *p, *q; p = &a[0]; q = &a[3]; printf("%ld\n", q - p); return ; } int main() { // test1(); // test2(); test3(); return 0; }
- 兩個(gè)相同類型的指針可以相互賦值
#include <stdio.h> void test4() { int a = 100; int *p, *q; p = &a; printf("a=%d %d\n", a, *p); q = p; printf("*q=%d\n", *q); *q = 999; printf("a=%d\n", a); } int main() { // test1(); // test2(); // test3(); test4(); return 0; }
到此這篇關(guān)于C語(yǔ)言由淺入深理解指針的文章就介紹到這了,更多相關(guān)C語(yǔ)言指針內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mfc入門(mén)教程之實(shí)現(xiàn)一個(gè)簡(jiǎn)單的計(jì)算器
這篇文章主要介紹了mfc入門(mén)教程,手把手教你如何開(kāi)發(fā)一個(gè)簡(jiǎn)單的計(jì)算器,需要的朋友可以參考下2019-04-04淺析C/C++中的可變參數(shù)與默認(rèn)參數(shù)
C支持可變參數(shù)的函數(shù),這里的意思是C支持函數(shù)帶有可變數(shù)量的參數(shù),最常見(jiàn)的例子就是我們十分熟悉的printf()系列函數(shù)。我們還知道在函數(shù)調(diào)用時(shí)參數(shù)是自右向左壓棧的2013-09-09使用Objective-C獲取IPHONE手機(jī)IMSI序列號(hào)
這篇文章主要介紹了使用Objective-C獲取IPHONE手機(jī)IMSI序列號(hào)的方法以及通過(guò)IMSI序列號(hào)獲取運(yùn)營(yíng)商、手機(jī)號(hào)的方法,非常的實(shí)用,有需要的小伙伴可以參考下。2015-04-04Windows配置VSCode+CMake+Ninja+Boost.Test的C++開(kāi)發(fā)環(huán)境(教程詳解)
這篇文章主要介紹了Windows配置VSCode+CMake+Ninja+Boost.Test的C++開(kāi)發(fā)環(huán)境,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05深入探討linux下進(jìn)程的最大線程數(shù)、進(jìn)程最大數(shù)、進(jìn)程打開(kāi)的文件數(shù)
本篇文章是對(duì)linux下進(jìn)程的最大線程數(shù)、進(jìn)程最大數(shù)、進(jìn)程打開(kāi)的文件數(shù)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05VSCode?IDE?配置環(huán)境過(guò)程解析
這篇文章主要介紹了VSCode?IDE?環(huán)境配置,這里說(shuō)的是僅使用?VSCode?創(chuàng)建C/CPP項(xiàng)目時(shí)的配置,VSCode?有代碼提示,?定位來(lái)源和各種快捷鍵,?更適合日常編碼工作,需要的朋友可以參考下2022-02-02