指針的定義
? 指針是一個(gè)變量
? 指針只能存地址
? 指針占據(jù)8個(gè)字節(jié)空間
總結(jié): 指針是一種保存變妥地址的變量
int main(){
int *a;
int *b;
printf("a的大卸颉:%d\n",sizeof(a));
printf("a的地址:%p\n",a);
printf("%d\n",sizeof(b));
}
輸出:
a的大小:8
a的地址:12335667677
8
指針的聲明
int *p;//聲明一個(gè)int類型的指針p
char *p;//聲明一個(gè)char類型的指
int *arr[5];//聲明一個(gè)指針數(shù)組掂榔,數(shù)組內(nèi)有5個(gè)元素继效,每個(gè)元素都是指向int 類型對(duì)象的指針
int **p;//聲明一個(gè)指針,指針指向一個(gè)int 類型的指針
? 指 針的聲明相對(duì)于普通變量的聲明多了一個(gè)一元運(yùn)算符
? 運(yùn)算符"* " 是間接尋址或者間接引用運(yùn)算符装获。當(dāng)它作用于指針時(shí)瑞信,將訪問指針?biāo)赶虻膶?duì)象。
? p 是一個(gè)指針穴豫,保存 著一個(gè)地址凡简,該地址指向內(nèi)存中的一個(gè)變量; *p 則會(huì)訪問這個(gè)地址所指向的變量。
? 聲明一個(gè)指針變量并不會(huì)自動(dòng)分配任何內(nèi)存秤涩。
? 在對(duì)指針進(jìn)行間接訪間之前帜乞,指針必須進(jìn)行初始化:或是使他指向現(xiàn)有的內(nèi) 存,或者給他動(dòng)態(tài)分配內(nèi)存溉仑,否則這個(gè)指針會(huì)變成野指針挖函。
指針初始化
方法1:使指針指向現(xiàn)有內(nèi)存
int a=5;
int *p=&a;
? : 定義的時(shí)候表明是一個(gè)指針變量,使用的時(shí)候表示取地址的值
&:取 某一個(gè)變量地址
方法2:動(dòng)態(tài)分配內(nèi)存給指針
int *p;
p=(int*)malloc(sizeof(int)*10);//malloc函數(shù)用于動(dòng)態(tài)分配內(nèi)存
free(p);//free函數(shù)用于釋放一塊已經(jīng)分配的內(nèi)存
指針的初始化實(shí)際上就是給指針一個(gè)合法的地址浊竟,讓程序能夠清楚地知道指針的指向怨喘,而不至于變?yōu)橐爸羔?/p>
指針的類型
判斷指針類型的方法: 去掉星號(hào)*和變量名就是指針的類型
int p;//p是一個(gè)普通的整形變量
int *p;//p是一個(gè)返回整形數(shù)據(jù)的指針
P與 *結(jié)合所以說明P 是一個(gè)指針然后再與int 結(jié)合說明指針?biāo)赶虻膬?nèi)容的類型為int型.
int p[3];//p是一個(gè)由整形數(shù)據(jù)組成的數(shù)組
int *p[3];//p是一個(gè)由返回整形數(shù)據(jù)的指針的數(shù)組
int (*p)[3];//p是一個(gè)指向由整形數(shù)據(jù)組成的數(shù)組的指針
int **p;//p是一個(gè)指向整形的指針的指針
int p(int);//p是一個(gè)參數(shù)和返回值都為int的一個(gè)函數(shù)
int (*p)(int);//p是一個(gè)指向有一個(gè)整形參數(shù)且返回類型為整形的函數(shù)的指針
?P與[ ]結(jié)合 說明 P 是一個(gè)數(shù)組,然后與int 結(jié)合說明數(shù)組里的元素是整型的
? P與[ ]結(jié)合, 因?yàn)槠鋬?yōu)先級(jí)比高,所以P 是一個(gè)數(shù)組,然后再與結(jié)合,說明數(shù)組里的元素是指針類型,然后再與int結(jié)合,說明指針?biāo)赶虻膬?nèi)容的類型是整型
? P與[結(jié)合說明P是一個(gè)指針,然后再與[ ]結(jié)合,(與“()”結(jié)合這步可以忽略只是為了改變優(yōu)先級(jí))振定,說明指針?biāo)赶虻膬?nèi)容是一個(gè)數(shù)組必怜,然后再與int 結(jié)合,說明數(shù)組里的元素是整型
? P與結(jié)合后频,說明P 是一個(gè)指針梳庆,然后再與*結(jié)合,說明指針?biāo)赶虻脑厥侵羔樔缓笤倥cint 結(jié)合卑惜,說明該指針?biāo)赶虻脑厥钦蛿?shù)據(jù)
? P與()結(jié)合說明P 是一個(gè)函數(shù)膏执,然后進(jìn)入()里分析,說明該函數(shù)有一個(gè)整型變量的參數(shù)露久,然后再與外面的回 結(jié)合 說明函數(shù)的返回值是一個(gè)整型數(shù)據(jù)
? P與指針結(jié)合說明P 是一個(gè)指針更米,然后與()結(jié)合說明指針指向的是一個(gè)函數(shù),然后再與()里的int 結(jié)合說明函數(shù)有一個(gè)int 型的參數(shù),再與最外層的int結(jié)合,說明函數(shù)的返回類型是整型
指針的指向內(nèi)容
指針存儲(chǔ)的內(nèi)容為變量的地址毫痕,也就是說指針的是一個(gè)指向作用征峦,指向變量所存儲(chǔ)的內(nèi)容
int main(){
int a=5;
int *p=&a;
return 0;
}
指針的運(yùn)算
可以對(duì)指針變量p 進(jìn)行p++、P--消请、p + i 等操作栏笆,所得結(jié)果也是一個(gè)指針,只是指針?biāo)赶虻膬?nèi)存地址相比于 p 所指的內(nèi)存地址前進(jìn)或者后退了i(對(duì)應(yīng)指針指向類型對(duì)應(yīng)大小個(gè))操作數(shù)臊泰。
數(shù)組與指針
數(shù)組的數(shù)組名其實(shí)可以看作一個(gè)指針蛉加,因?yàn)閿?shù)組名是指向數(shù)組的第一個(gè)元素, 數(shù)組名本身是沒有占有內(nèi)存
另外一種解釋是將數(shù)組名指向數(shù)組的第0個(gè)單元缸逃, 那么 (array+n) 也就是一個(gè)指向數(shù)組里的第n個(gè)單元的指針
?###指針數(shù)組
指針數(shù)組七婴,是一個(gè)數(shù)組, 數(shù)組中的每一個(gè)元素都是指針
int *date[10]={NULL};
for(int i=0;i<10;++i){
date[i]=(int*)malloc(sizeof(int)*10);
}
date[1][2]=1;
}
對(duì)于上面的定義和初始化察滑,data是指針數(shù)組的名字打厘,也 就是指向指針數(shù)組首元素的指針.(指針的指針). data[ i ] 是data這一個(gè)數(shù)組的第i個(gè)元素,也就是一個(gè)指向 int的指針指針可以當(dāng)成數(shù)組來使用贺辰, d a t a [ i ][ j ] 和 * ( data [ i ] + j ) 是等價(jià)
經(jīng)過上述代碼創(chuàng)建的一個(gè)指針數(shù)組data的使用和int data[10][10]基本相同户盯,區(qū)別 在于后者保證數(shù)組和數(shù)組之間的內(nèi)存地址是連續(xù)的.data[0][ 9] 和 data[1][ 0] 是連續(xù)的嵌施,而如果使用指針數(shù)組方式創(chuàng)建的data, 不能保證data[0][ 9] 和 data[1][ 0] 在內(nèi)存上連續(xù)
數(shù)組指針
數(shù)組指針,是一個(gè)指針莽鸭, 它指向一個(gè)數(shù)組
int (*)date[10]=NULL;
int func(int date[ ][20]){
}
數(shù)組作為參數(shù)傳入函數(shù)的時(shí)候吗伤,對(duì)千被調(diào)用的函數(shù)參數(shù)就是指針,因 此硫眨,這里參數(shù)是一個(gè)“元素為int [ 28 ] "的數(shù)組(數(shù)組的數(shù)組)足淆,因 此 在函數(shù)內(nèi)部,data實(shí)際上就是一 個(gè)”指向 i n t [ 28 ] "的指 針( int (* )[ 28 ] )
? 盡量不要對(duì)數(shù)組和指針使用sizeof
? 當(dāng)且僅當(dāng)如malloc ( 10 * sizeof ( int ) ) 時(shí)使用sizeof
指針與函數(shù)
? 函數(shù)指針是指向函數(shù)的指針變量
? 通常我們說的指針變量是指向一個(gè)整型礁阁、字符型或數(shù)組等變量巧号, 而函數(shù)指針是指向函數(shù)
? 函數(shù)指針可以像一般函數(shù)一祥,用于調(diào)用函數(shù)姥闭、傳遞參數(shù)
#include<stdio.h>
//指針和函數(shù)的關(guān)系
//通過指針 間接訪問某個(gè)內(nèi)存
void test(int *pa,int *pb){
(*pa)++;
(*pb)++;
}
//函數(shù)接收數(shù)組時(shí)丹鸿,必須知道數(shù)組元素個(gè)數(shù)
//函數(shù)里面是通過指針變量;來接收數(shù)組地址
//指針變量無法確定指向的內(nèi)容的大小
void test2(int *p,int count){
for(int i=0;i< count;i++){
(*(p+i))++;//p[i]++
}
}
int main(){
int a=10;
int b=20;
test(&a,&b);
int num[5]={1,2,3,4,5};
test2(num,5);
for(int i=0;i<5;i++){
printf("%d ",num[i]);
}
return 0;
}
函數(shù)指針聲明
typedef int (*fun_ptr)(int,int);
函數(shù)指針變量可以作為某個(gè)函數(shù)的參數(shù)來使用的棚品,回調(diào)函數(shù)就是一個(gè)通過函數(shù)指針調(diào)用的 函數(shù)靠欢。也就是說回調(diào)函數(shù)是由別人的函數(shù)執(zhí)行時(shí)調(diào)用你實(shí)現(xiàn)的函數(shù)
結(jié)構(gòu)體
需要一種類型,這種類型可以保存多種數(shù)據(jù)
如何定義結(jié)構(gòu)體類型:內(nèi)部類型不能賦初值
#include<stdio.h>truct student{
int age;
char sex;
char name[10];
}
如何使用:
int a=10;
struct student xw;
struct student lw={40,'m',"隔壁老王"}
lw.age=35;
結(jié)構(gòu)體類型字節(jié)數(shù)計(jì)算:
*/
int main(){
struct preson{
int age;
float height;
};
struct preson xw;
struct preson *p=&xw;
xw.age=20;
xw.height=180;
p->age=30;
p->height=180;
//將結(jié)構(gòu)體保存到文件
FILE *fp=
fopen("/Users/Public/Desktop/test.txt","r+") ;
struct preson zs;
fread(&zs,sizeof(struct person),1,fp);
printf("age:%d height:%f\n",zs.age,zs.height);
return 0;
}
頭文件與實(shí)現(xiàn)文件實(shí)例之計(jì)算器
? 計(jì)算器的頭文件Calculator.h
#include<stdio.h>
//加法
int add(int a,int b);
//減法
int minus(int a,int b);
//乘法
int multiply(int a,int b) ;
//除法
int devide(int a,int b);
? 計(jì)算器的實(shí)現(xiàn)函數(shù)Calculator.cpp
#include"Calculator.h"
//加法
int add(int a,int b){
return a+b;
}
//減法
int minus(int a,int b){
return a-b;
}
//乘法
int multiply(int a,int b) {
return a*b;
}
//除法
int devide(int a,int b){
if(b==0){
return 0;
}else{
return a/b;
}
}
? 計(jì)算器main函數(shù)入口
#include<stdio.h>
#include"Calculator.h"
//2.將不同的功能模塊用不同的.h .cpp來封裝
//.h頭文件 函數(shù)聲明(不能實(shí)現(xiàn))
//.cpp .c實(shí)現(xiàn)文件
int main(){
int result=add(1,1);
printf("1+1=%d\n",result);
printf("1+1=%d\n",add(1,1));
printf("1+1=%d\n",minus(2,1));
printf("1+1=%d\n",multiply(2,2));
printf("1+1=%d\n",devide(2,2));
return 0;
}
文件操作訓(xùn)練之字符串查找
mystring.h
//計(jì)算字符串的長(zhǎng)度
int length(char *p){
int i = 0;
for(; p[i] != '\0'; i++);
return i;
}
int find(char *sentence, char *word){
//1.獲取兩個(gè)字符串的長(zhǎng)度
int sLength = length(sentence);
int wLength = length(word);
printf("%d %d\n", sLength, wLength);
return 0;
}
mystring.cpp
#include <stdio.h>
#include "myString.h"
//%s 遇到空格或者\(yùn)n
//scanf不能輸入帶空格的字符串
//只能自己定義一個(gè)輸入語句的方法
void myScanf(char *p){
int i = 0;
while (1) {
char c = getchar();
if (c == '\n') {
p[i] = '\0';
break;
}
p[i] = c;
i++;
}
}
void input(char *p, char *des){
//提示用戶操作
printf("%s:", des);
//輸入語句
myScanf(p);
}
//計(jì)算字符串的長(zhǎng)度
int length(char *p){
int i = 0;
//for (; p[i] != '\0'; i++);
while (1) {
if (p[i] == '\0') {
break;
}
i++;
}
return i;
}
int find(char *sentence, char *word){
//1.獲取兩個(gè)字符串的長(zhǎng)度
int sLength = length(sentence);
int wLength = length(word);
//2.判斷查詢的字符串長(zhǎng)度是否比句子短
if (sLength < wLength) {
return 0;
}
/*
hjako jack ,jac;
i = 2
jac
j = 2
*/
int start = 0;
int count = 0;
for (int i = 0; i < sLength; i++) {
//記錄當(dāng)前開始的位置
start = i;
//從當(dāng)前位置開始去和查找的單詞進(jìn)行比較
int j = 0;
for(; j < wLength; j++){
//判斷j對(duì)應(yīng)的值和start+j比較
if (sentence[start+j] != word[j]) {
break;
}
}
//判斷怎么出來的
if (j == wLength){
//都相同
//將i的值定位到start+j的位置
i = start + j-1;
count++;
}
}
return count;
}
main.cpp
#include <stdio.h>
#include "myString.h"
/*
* fafjalfjasdfjsadlf
* kfjakfj
* fslf
* ksdfjlafjalsf
*/
int main(int argc, const char * argv[]) {
char sentence[100] = {};
char word[20] = {};
input(sentence, "請(qǐng)輸入語句");
input(word, "請(qǐng)輸入查找的單詞");
int count = find(sentence, word);
printf("出現(xiàn)%d次\n", count);
return 0;
}