c语言把结构体首地址放入指针,C语言基础———指针,结构体指针,函数指针
指針基礎(chǔ)
一 指針就是地址,地址就是指針.指針存儲(chǔ)的是內(nèi)存的地址.
二 指針的定義
1.&表示取址運(yùn)算符,&a 可以取到 a 在內(nèi)存中的地址;打印地址的占位符為(%p),printf(“%p\n”,&a);
2. 指針變量的定義
指針變量是用來存放地址的.
指針定義的格式:
類型數(shù)據(jù) ?*變量名 ?= ?初始值;
int *p = NULL;*在這里表示p 是一個(gè)指針變量,不是運(yùn)算符.
printf(“%p\n”,p); 在打印指針的時(shí)候不需要使用取址運(yùn)算符(&),因?yàn)橹羔槺緛砭褪堑刂?
*p 指針為空時(shí),打印出來0x0的地址,為空.
int ?a = 10;
p = &a;
printf(“%p\n”,p);
訪問內(nèi)存中的數(shù)據(jù)有兩種方法:
1.直接訪問內(nèi)存中的數(shù)據(jù).
printf(“%p\n”,a);
2. 通過指針進(jìn)行訪問.
*也可以作為取值運(yùn)算符.* p 代表取到 p 指向內(nèi)存中存儲(chǔ)的數(shù)據(jù) ?printf(“%d\n”,*p);
int a = 10,b = 20;
int *p1 = &a;
int *p2 = &b;
對(duì)指針重新賦值,意味著指針重指向,也就是說指針指向一個(gè)新的地址.
p1 = p2;p1指向 c 的首地址
printf(“*p1 = %d,*?p2 = %d\n”,*p1,*p2);
int a = 15,b = 20;
int *p = &a;
int *p1 = &b;
單獨(dú)的* p 表示取值,* p = 11 表示向 p 指向的內(nèi)存中存入數(shù)據(jù).
*p = 11;
printf(“%d\n”,a);
int *p3 = &a;
p3 = p1;
*p1 = 8;
printf(“a = %d,b = %d\n”,a,b);a = 11,b = 8
經(jīng)典練習(xí)
int a?= 6,b?= 8,c = 10;
int *x = &a;
x = &c;
int *y = &b;
int *z = &c;
*z = 5;
*x = 12;
x = y;
*y = *x + *z;
printf(“a?= %d,b = %d,c = %d\n”,a,b,c);
指針中常見的問題
1.內(nèi)存編號(hào)比較小的存儲(chǔ)單元,是由系統(tǒng)控制的,不允許訪問.
int *p = NULL;
*p = 100; ? error
2.野指針,定義時(shí)沒有賦初始值,操作野指針是很危險(xiǎn)的
int *p;
*p = 100;error
3.定義指針時(shí),*怎么寫?
int *p?= NULL;推薦
int* p1 = NULL;
int *p1 = NULL;
int*p3 = NULL;
4.指針變量在內(nèi)存中占幾個(gè)字節(jié)
與數(shù)據(jù)類型無關(guān),在32位操作系統(tǒng)下,指針?biāo)甲止?jié)數(shù)是4位,在64位操作系統(tǒng)中,指針?biāo)甲止?jié)數(shù)是8位.
printf(“%lu\n”,sizeof(long *));
5. 修飾指針變量數(shù)據(jù)類型的作用
a. 指針變量數(shù)據(jù)類型,決定*(取值運(yùn)算符),取多少個(gè)字節(jié)的數(shù)據(jù);
定義指針的數(shù)據(jù)類型一定要和指向數(shù)據(jù)的數(shù)據(jù)類型一致,這樣才能把數(shù)據(jù)完整的取出來
int *p = NULL;
int a = 268;
p = &a;
printf(“%d\n”,*p);
char *c = NULL;
c = &a;
printf(“%d\n”,*c);
b.指針類型,決定指針變量加1操作時(shí),跳轉(zhuǎn)多少個(gè)字節(jié)
int *p = NULL;
printf(“%p\n”,p); //0x0
printf(“%p\n”,p+1);//0x4
printf(“%p\n”,p+2);//0x8
printf(“%p\n,p++);//打印的結(jié)果是:0x4? ?但是實(shí)際結(jié)果是:0x8
p+1 和 ?p++或++ p 的關(guān)系
相同:取到的都是下一個(gè)字節(jié)的地址
不同:++p和 p++ 造成指針的重指向
6.指針在數(shù)組中的應(yīng)用
int a[5] = {1,2,3,4,5};
數(shù)組名就是數(shù)組元素的首地址
printf(“%p\n”,a);
printf(“%p\n”,&a[0]);
printf(“%p\n”,p);
printf(“%p\n”,a+1);
printf(“%p\n”,&a[1]);
printf(“%p\n”,p+1);
printf(“%p\n”,a+2);
printf(“%p\n”,&a[2]);
printf(“%p\n”,p+2);
printf(“%d\n”,*a);
printf(“%d\n”,*(a +1));
printf(“%d\n”,*(a+2));
用指針遍歷數(shù)組
for(int i= 0;i < 5;i++){
printf(“%d\n”,*(a+i));
}
定義指針變量訪問數(shù)組中的元素
int *p =NULL;
p = a;
printf(“%p\n”,a);
printf(“%p\n”,p);
printf(“%d\n”,*p);
printf(“%d\n”,*(p+1));
printf(“%d\n”,*(p+2));
練習(xí)
有10個(gè)元素的數(shù)組,通過指針變量為元素隨機(jī)賦值[22 33]
7.數(shù)組名(數(shù)組元素的首地址) ? 與指向數(shù)組首地址的指針變量的區(qū)別:
a. 數(shù)組名(數(shù)組首地址) 是一個(gè)常量地址不能被修改
a = NULL;error
指針變量可以修改,可以重指向
b. 數(shù)組名(數(shù)組的首地址),用sizeof 計(jì)算得到的結(jié)果,整個(gè)數(shù)組所占的字節(jié)數(shù),而用 sizeof 計(jì)算指向數(shù)組元素首地址的指針變量得到是一個(gè)定值4或者8
printf(“%lu\ n”,sizeof(c));
//定義一個(gè)10個(gè)元素的數(shù)組,通過指針變量為元素隨機(jī)賦值[22 33],冒泡排序;
8.指針在字符串中的應(yīng)用
用% s 打印是從指針指向那個(gè)地址開始向后輸出
char string[] = “Canglaoshi”;
printf(“%s\n”,string);
printf(“%s\n”,string+1);
通過指針訪問里面的元素
數(shù)組名(數(shù)組元素的首地址) ?== 指針
*(string + 3) = ‘\0'
printf(“%s\ n”,string);
通過指針訪問元素
printf(“%c\ n”,*(string +3));
通過指針計(jì)算字符串的長度
int i= 0;
*(string +i) ?取到數(shù)組中對(duì)應(yīng)位置的值
while(*(string+i) != ‘\0’){//string[i]
i++;
}
printf(“%d\n”,i);
指針變量一定要和指向的數(shù)據(jù)類型相同
char *p = string;
int i = 0;
while(*(p+i) != ‘\0’){
i++;
}
char string[] = "canglaoshi I love you";//將字符串的首個(gè)字母大寫,并且將空格換成下劃線
char string[] = "canglaoshi I love you";
*string -= 32;
char *p = string;
if (string[0] >= 'a' && string[0] <='z') {
string[0] -= 32;
}
int i = 0;
while (*(string+i) != '\0') {
if (*(string + i) == ' ') {
*(string + i) = '-';
}
i++;
}
printf("%s\n",string);
//寫一個(gè)函數(shù)實(shí)現(xiàn)兩變量的交換
int a = 10;
int b = 20;
change(&a,&b);
printf("a = %d,b = %d\n",a,b); int a = 10,b = 20; int sum = 0,sub = 0;
sum = sumAndsub(a,b,&sub); printf("sum = %d,sub = %d\n",sum,sub); float a[10] = {0}; for (int i = 0; i < 10; i++) {
*(a+i) =arc4random()%21+10;
printf("%.2f ",*(a+i));
} printf("\n"); for (int i = 0; i < 10 - 1; i++) { for (int j = 0; j < 10 - i - 1;j++) {//??????????? if (a[j] > a[j + 1]) {//??????????????? float temp = 0;//??????????????? temp = a[j];//??????????????? a[j] = a[j + 1];//??????????????? a[j + 1] = temp;//??????????? } if (*(a + j) > *(a + 1 + j)) { float temp = 0;
temp = *(a +j);
*(a + j) = *(a + j + 1);
*(a + j + 1) = temp;
}
}
} printf("\n"); for (int i = 0; i < 10; i++) {
printf("%.2f ",*(a+i));
}
結(jié)構(gòu)體指針
1.形參和實(shí)參的區(qū)別
a. 形參:定義的時(shí)候?qū)懙膮?shù),(起一個(gè)描述的作用,沒有實(shí)際的意義)
b. 實(shí)參:函數(shù)實(shí)際調(diào)用時(shí)傳進(jìn)來的參數(shù)
形參和實(shí)參的傳遞是單向的.
2.結(jié)構(gòu)體嵌套
在定義結(jié)構(gòu)體的時(shí)候,結(jié)構(gòu)體的成員變量也可以是結(jié)構(gòu)體.
3.結(jié)構(gòu)體指針
指向結(jié)構(gòu)體的指針叫結(jié)構(gòu)體指針.
數(shù)據(jù)類型 ?+ * ?+?變量名 + 初始值;
Student ?stu1 = {“l(fā)isi”,’M’,29};
指針變量指向結(jié)構(gòu)體變量的首地址,相當(dāng)于指向結(jié)構(gòu)體第一個(gè)成員變量的地址
Student *p = &stu1;
結(jié)構(gòu)體指針的訪問
printf(“%s”,(*p).name);
通過指針變量訪問結(jié)構(gòu)體變量的成員
printf(“%s,%c,%d\n”,p->name,p->sex,p->age);
4——>:指向操作符
只有定義的是結(jié)構(gòu)體變量的首地址,才可以使用(—>指向操作符)訪問結(jié)構(gòu)體變量
printf(“%s,%c,%d\n”,p->name,p->sex,p->age);
5.float x1 = 0.1;
float x2 = 1.;
float x3 = 1.f;
float x4 =1.0f;
float x5 = 1;
6.結(jié)構(gòu)體數(shù)組與指針的關(guān)系
結(jié)構(gòu)體數(shù)組的數(shù)組名是一個(gè)結(jié)構(gòu)體指針常量.
int a[5] = {1,2,3,4,5};
int *p = a;//數(shù)組名就是數(shù)組的首地址.
printf(“%d\n”,*p);
*stu ? : ? stu[0] ?//代表的都是數(shù)組中第一個(gè)元素,
*(stu + 1) :stu[1] ?// 代表的都是數(shù)組中的第二個(gè)元素.
*(stu + 2) ? :stu[2] ?//代表的是數(shù)組中的第三個(gè)元素.
訪問數(shù)組中結(jié)構(gòu)體元素的屬性
*stu.name ? :stu[0].name
(*(stu + 1)).name ?: ?stu[1].name
—>:指向操作符 ?:使用的時(shí)候一定要保證指針指向結(jié)構(gòu)體變量的首地址
stu—> name ? :stu[0].name
(stu + 1) —>name ?:stu[1].name
(stu + 2)——>name ? : stu[2].name
7.遍歷結(jié)構(gòu)體數(shù)組的時(shí)候,需要向函數(shù)中傳入數(shù)組和長度.
8.指針數(shù)組(也就是指向指針的指針)
int ?a?= 3,b = 4,c= ?5;
數(shù)組中的元素都是指針(地址)數(shù)組,就是指針數(shù)組.
int *array[3] = {&a,&b,&c};//3*8個(gè)字節(jié)
printf(“%p\n”,array[0]);
printf(“%p\n”,&a);
printf(“%d\n”,**array);//*array? 取到地址 ?**array ?取到地址里的值
printf(“%d\ n”,*(*(arrary + 1)));
二.函數(shù)指針
函數(shù)指針的聲明方法為:
函數(shù)類型 ?(標(biāo)示符 ?指針變量名 )(形參列表);
函數(shù)類型說明函數(shù)的返回類型,”(標(biāo)識(shí)符 指針變量)”中的括號(hào)不能省,若省略整體則成為一個(gè)函數(shù)說明,說明了一個(gè)返回的數(shù)據(jù)類型是指針的函數(shù),后面的”形參列表"表示指針變量指向的函數(shù)所帶來的參數(shù)列表.
例如:
int func(int x); 聲明一個(gè)函數(shù)
int (*f)(int x);
函數(shù)指針
1.函數(shù)指針類型的確定步驟
1?把函數(shù)名換成(*) ? ?void (*)() ? ?int(*)(int,int)
2?如果有參數(shù),把參數(shù)名去掉,只保留參數(shù)類型 ?void (*)() ? int (*)(int,int)
3?格式
指針類型 ?*指針名 ?= 初始值;
char *p?= NULL;
函數(shù)指針的類型
返回值類型(*函數(shù)指針變量名)(參數(shù)類型1,參數(shù)類型2.....) = 初始值;
函數(shù)后面的()是函數(shù)調(diào)用符.
注意: ?函數(shù)指針變量名不能和指針重名
int sum(int a,int b){
return a+b;
}
int (*Sum)(int,int);
Sum = sum;
int y = Sum(3,5);
printf(“%d\n”,y);
同一個(gè)函數(shù)指針可以指向不同的函數(shù),但是(前提是:函數(shù)指針的類型必須一致)
2.typedef 原始類型 ?新類型;
給函數(shù)指針類型起別名
typedef int (*FUN)(int,int);
typedef void (*HELLO)
typedef ?返回值類型(*新類型名)(參數(shù)類型1,參數(shù)類型2.....)
3.函數(shù)回調(diào)
函數(shù)回調(diào):就是用函數(shù)指針來調(diào)用函數(shù)
函數(shù)名就是指針,存放的函數(shù)的首地址
4.動(dòng)態(tài)排序
就是不斷的改變排序的條件,根據(jù)不同的條件,調(diào)用不同的函數(shù),進(jìn)行排序.
5.枚舉
定義:一組有符號(hào)的整形常量,一一列舉所有的狀態(tài),羅列出所有可能的結(jié)果
enum season {
spring,
summer,
autumn,
winter};
printf(“%d\n”,spring);
枚舉經(jīng)常和 swith 合用
枚舉間接提高了代碼的可讀性
將人能識(shí)別的表示符,與計(jì)算機(jī)能識(shí)別的數(shù)字建立聯(lián)系
6.宏只做簡單的替換,在預(yù)編譯的時(shí)候完成替換
宏命名規(guī)范:
1?純大寫
2?k + ?大駝峰
無參宏直接進(jìn)行定義,有參宏可以使用常量表達(dá)式
#define SUM(A,B) ?((A) - (B))?// 最安全的方式
有參數(shù)的宏,只做簡單的替換運(yùn)算,不會(huì)判斷運(yùn)算符的優(yōu)先級(jí)
int p = SUM(3 + 7,5 + 6) * 3;//3 + 7 * 5 + 6
7.條件編譯
第一種
#ifdef ?MY
printf(“Hello Word!!");
#else
printf(“明天考試!!");
#endif
特點(diǎn):如果標(biāo)示符被# define 過,就會(huì)執(zhí)行代碼段1,否則就會(huì)執(zhí)行代碼段2
第二種方式
#ifndef? 標(biāo)示符
代碼段1
#else
代碼段2
#endif
特點(diǎn):如果標(biāo)示符沒有被#define過,就會(huì)執(zhí)行代碼段1;如果被定義過,,就編譯代碼段2
第三種方式
#if ?常量表達(dá)式
代碼段1
#else
代碼段2
#endif
#if MY
printf(“你好藍(lán)歐!!");
#else
printf(“你好中國!!");
#endif
特點(diǎn):如果常量表達(dá)式非0,就執(zhí)行代碼段1,否則執(zhí)行代碼段2
8.const 常量修飾符
被 const修飾的常量是不能重新賦值的
總結(jié)
以上是生活随笔為你收集整理的c语言把结构体首地址放入指针,C语言基础———指针,结构体指针,函数指针的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: amd服务器6300系列,AMD新款Op
- 下一篇: Mac上Unity打ab包报错 Movi