国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

C語(yǔ)言進(jìn)階:指針進(jìn)階續(xù)

ingood / 1503人閱讀

摘要:故使用無(wú)具體類型,又稱通用類型,即可以接收任意類型的指針,但是無(wú)法進(jìn)行指針運(yùn)算解引用,整數(shù)等。求指針?biāo)甲止?jié)而不是解引用訪問(wèn)權(quán)限大小。數(shù)組就是整個(gè)數(shù)組的大小,數(shù)組元素則是數(shù)組元素的大小,指針大小都為。

指針進(jìn)階續(xù)

續(xù)前文《C語(yǔ)言進(jìn)階:指針進(jìn)階》

回調(diào)函數(shù)

回調(diào)函數(shù)定義

回調(diào)函數(shù):通過(guò)函數(shù)指針調(diào)用的函數(shù),或者說(shuō)使用函數(shù)指針調(diào)用函數(shù)這樣的機(jī)制被稱為回調(diào)函數(shù)。回調(diào)函數(shù)不由實(shí)現(xiàn)方直接調(diào)用,而是作為特殊條件下的響應(yīng)。

概念無(wú)關(guān)緊要,理解并熟練運(yùn)用這種方法才更為重要。

快速排序 qsort

qsort函數(shù)邏輯
void qsort(void* base, size_t num, size_t width, int (*cmp)(const void* e1, const void* e2));

qsort無(wú)返回值,有四個(gè)參數(shù)。分別為base:起始地址,num:元素個(gè)數(shù),width:元素大小以及compare:比較函數(shù)。可與冒泡排序作對(duì)比。

//冒泡排序void Bubble_sort(int arr[], int sz) {	for (int i = 0; i < sz - 1; i++) { 		for (int j = 0; j < sz - 1 - i; j++) { 			//比較函數(shù)			if (arr[j] > arr[j + 1]) {				int tmp = arr[j];				arr[j] = arr[j + 1];				arr[j + 1] = tmp;			}        }    }}

與冒泡排序作對(duì)比發(fā)現(xiàn),冒泡排序僅需起始地址和元素個(gè)數(shù)即可,暗含了其他信息。由于過(guò)度具體化,冒泡排序只能排序整型數(shù)組,且比較函數(shù)過(guò)于簡(jiǎn)單無(wú)需多帶帶列出。

因?yàn)?code>qsort排序可適用于多種類型如浮點(diǎn)型,字符型,自定義類型的數(shù)據(jù),故無(wú)法規(guī)定具體類型,所以需要多個(gè)參數(shù)去描述元素的基本信息。

qsort之所以能夠適應(yīng)多種數(shù)據(jù),是因?yàn)閰?shù)void* base再搭配上numwidth就描述出任意一種類型。

為什么將參數(shù)base的類型定義為void*呢?如下述代碼所示。

char* p1 = &a;//從int*到char*類型不兼容char* p2 = &f;//從float*到char*類型不兼容void* p1 = &a;void* p2 = &f;

確定類型的地址之間直接賦值會(huì)提示類型不兼容,強(qiáng)制轉(zhuǎn)化也可能會(huì)導(dǎo)致精度丟失。

故使用無(wú)(具體)類型void*,又稱通用類型,即可以接收任意類型的指針,但是無(wú)法進(jìn)行指針運(yùn)算(解引用, ± ± ±整數(shù)等)。

p1++;   *p1;   p1 - p2;   p1 > p2;//表達(dá)式必須是指向完整對(duì)象類型的指針
  1. base:用于存入數(shù)據(jù)的起始地址。類型定義為void*,可接受任意類型的指針。

  2. num:待排序的元素個(gè)數(shù)。

  3. width:元素寬度,所占字節(jié)大小。

明確了排序的起始位置,元素個(gè)數(shù)和元素大小,貌似已經(jīng)夠了。但是并無(wú)法排序所有類型,因此必須自定義一個(gè)抽象的比較函數(shù)指定元素的比較方式。

  1. cmp:比較函數(shù),用于指定元素的比較方式。

    • elem1小于elem2,返回值小于0
    • elem1大于elem2,返回值大于0
    • elem1等于elem2,返回值為0
  2. elem1elem2:進(jìn)行比較的兩個(gè)元素的地址作參數(shù)。

qsort可以說(shuō)是一個(gè)半庫(kù)函數(shù)半自定義函數(shù)。自定義在于其函數(shù)最后一個(gè)參數(shù)為比較函數(shù),該函數(shù)內(nèi)部實(shí)現(xiàn)自由,但返回值必須按照規(guī)定返回相應(yīng)的數(shù)值。

小結(jié)

需要qsort函數(shù)排序各種類型的數(shù)據(jù),

  • base起始地址不可為固定的指針類型,只能用void*
  • 既然是通用類型還要明確比較元素的個(gè)數(shù)和大小。
  • 最后,排序最核心的比較大小,為適應(yīng)不同的類型元素必須自定義專門(mén)的比較函數(shù)。
qsort實(shí)現(xiàn)冒泡排序
//比較函數(shù):整型#include int int_cmp(const void* e1, const void* e2) {	return *(int*)e1 - *(int*)e2;}int main() {	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };	int sz = sizeof(arr) / sizeof(arr[0]);	qsort(arr, sz, sizeof(arr[0]), int_cmp);	return 0;}

比較函數(shù)int_com不需要傳參,作為回調(diào)函數(shù)由qsort直接調(diào)用。比較函數(shù)的傳參過(guò)程由qsort內(nèi)部實(shí)現(xiàn)。

qsort實(shí)現(xiàn)結(jié)構(gòu)體排序
#include struct stu {	char* name;	short age;	float score;};//按照成績(jī)排序int score_cmp(const void* e1, const void* e2) {	//1.升序    return ((struct stu*)e1)->score - ((struct stu*)e2)->score;	//2.降序    return ((struct stu*)e2)->score - ((struct stu*)e1)->score;}//按照名字排序int name_cmp(const void* e1,const void* e2) {	return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);}int main() {	struct stu s[3] = {         { "張三", 22, 99.5f },{ "李四", 21, 66.4f },{ "王五", 18, 80.1f }     };	int sz = sizeof(s) / sizeof(s[0]);	//1.    qsort(s, sz, sizeof(s[0]), name_cmp);	//2.    qsort(s, sz, sizeof(s[0]), score_cmp);	return 0;}

由此可得,提取出一個(gè)比較函數(shù),具體交換的方式由qsort內(nèi)部實(shí)現(xiàn)。

模擬實(shí)現(xiàn)qsort

qsort的函數(shù)邏輯,實(shí)現(xiàn)冒泡排序。

//打印函數(shù)void print_arr(int arr[],int sz) {	for (int i = 0; i < sz; i++) {		printf("%d ", arr[i]);	}}//交換函數(shù)void Swap(char* buf1, char* buf2, size_t width) {	for (size_t i = 0; i < width; i++) {//寬度次		char tmp = *buf1;		*buf1 = *buf2;		*buf2 = tmp;		buf1++;		buf2++;	}}//比較函數(shù)int cmp(const void* e1, const void* e2) {	return *(int*)e1 - *(int*)e2;}//排序函數(shù)void my_bubble_sort(void* base, size_t num, size_t width, int(*cmp)(const void* e1, const void* e2)) {	for (size_t i = 0; i < num - 1; i++) {		for (size_t j = 0; j < num - 1 - i; j++) {			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0) {//以字節(jié)為單位				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);			}		}	}}int main() {	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };	int sz = sizeof(arr) / sizeof(arr[0]);	my_bubble_sort(arr, sz, sizeof(arr[0]), cmp);	print_arr(arr, sz);	return 0;}

地址統(tǒng)一強(qiáng)轉(zhuǎn)為char*,以最小字節(jié)單位一個(gè)字節(jié)進(jìn)行比較和交換,使代碼更具有普適性。

如果需要排序結(jié)構(gòu)體則只需要在前文代碼中主函數(shù)里替換my_qsort且把比較函數(shù)替換Name_cmp即可。

//1.my_qsort(s, sz, sizeof(s[0]), name_cmp);//2.my_qsort(s, sz, sizeof(s[0]), score_cmp);

?

指針和數(shù)組筆試題解析

數(shù)組辨析題

注意點(diǎn)。數(shù)組名代表整個(gè)數(shù)組:

  1. sizeof(數(shù)組名)
  2. &數(shù)組名

除此以外,數(shù)組名都是代表首元素地址。

一維數(shù)組
int a[] = { 1,2,3,4 };printf("%d/n", sizeof(a));//16printf("%d/n", sizeof(a + 0));//4/8printf("%d/n", sizeof(*a));//4printf("%d/n", sizeof(a + 1));//4/8printf("%d/n", sizeof(a[1]));//4printf("%d/n", sizeof(&a));//4/8printf("%d/n", sizeof(*&a));//16printf("%d/n", sizeof(&a + 1));//4/8printf("%d/n", sizeof(&a[0]));//4/8printf("%d/n", sizeof(&a[0] + 1));//4/8
  1. 只有數(shù)組名多帶帶放在sizeof內(nèi)部才是整個(gè)數(shù)組。

    a+0放在sizeof內(nèi)部表示首元素地址+0。

  2. 只要是地址,不管是什么類型的地址大小都是4/8

    基本類型指針,數(shù)組指針,函數(shù)指針大小都是4/8個(gè)字節(jié),故sizeof(&a)=sizeof(int(*)[4])=4sizeof()求指針?biāo)甲止?jié)而不是解引用訪問(wèn)權(quán)限大小。

  3. *&在一起會(huì)抵消。

    sizeof(*&a),&a為整個(gè)數(shù)組的地址類型int(*)[4],解引用后int[4]大小為16。

字符數(shù)組
char arr[] = { "a","b","c","d","e","f" };printf("%d/n", sizeof(arr));//6printf("%d/n", sizeof(arr + 0));//4/8printf("%d/n", sizeof(*arr));//1printf("%d/n", sizeof(arr[1]));//1printf("%d/n", sizeof(&arr));//4/8printf("%d/n", sizeof(&arr + 1));//4/8printf("%d/n", sizeof(&arr[0] + 1));//4/8printf("%d/n", strlen(arr));//隨機(jī)值xprintf("%d/n", strlen(arr + 0));//隨機(jī)值xprintf("%d/n", strlen(*arr));//報(bào)錯(cuò)printf("%d/n", strlen(arr[1]));//報(bào)錯(cuò)printf("%d/n", strlen(&arr));//隨機(jī)值xprintf("%d/n", strlen(&arr + 1));//隨機(jī)值x-6printf("%d/n", strlen(&arr[0] + 1));//隨機(jī)值x-1
  1. sizeof(*arr)*arr對(duì)首元素地址解引用,計(jì)算首元素所占空間大小。

    strlen(*arr)*arr依然是首元素,strlen把a(bǔ)也就是97當(dāng)成地址,訪問(wèn)到非法內(nèi)存所以報(bào)錯(cuò)。

2.strlen(&arr)雖然是整個(gè)數(shù)組的地址,但依然是從首元素開(kāi)始的,所以strlen依然從第一個(gè)元素開(kāi)始找。

? strlen(&arr+1),先計(jì)算&arr+1然后再傳參過(guò)去,也就是跳過(guò)了整個(gè)數(shù)組去找。

sizeofstrlen的區(qū)別

  • sizeof — 操作符 — 以字節(jié)為單位,求變量或類型所創(chuàng)建變量的所占空間的大小

sizoef不是函數(shù),計(jì)算類型是必須帶上類型說(shuō)明符()sizoef內(nèi)容不參與運(yùn)算,在編譯期間便轉(zhuǎn)化完成。

  • strlen — 庫(kù)函數(shù) — 求字符串長(zhǎng)度即字符個(gè)數(shù),遇/0停止。

庫(kù)函數(shù),計(jì)算字符串長(zhǎng)度沒(méi)有遇到/0就會(huì)一直持續(xù)下去。返回類型size_t,參數(shù)char* str ,接收的內(nèi)容都會(huì)認(rèn)為是char*類型的地址。

一個(gè)求變量所占空間,一個(gè)求字符串大小,二者本身是沒(méi)有關(guān)系的,但總有人把二者綁在一起“混淆視聽(tīng)”。

字符串?dāng)?shù)組

首先明確二者的區(qū)別:

//1.字符初始化數(shù)組char arr[] = { "a","b","c","d","e","f" };//[a] [b] [c] [d] [e] [f]//2.字符串初始化數(shù)組char arr[] = "abcdef";//[a] [b] [c] [d] [e] [f] [/0]

字符初始化數(shù)組,存了什么元素?cái)?shù)組里就是什么元素。而字符串初始化數(shù)組,除了字符串中可見(jiàn)的字符外,還有字符串末尾隱含的/0/0存在于字符串的末尾,是自帶的,雖不算字符串內(nèi)容,但是字符串中的字符。

char arr[] = "abcdef";printf("%d/n", sizeof(arr));//7printf("%d/n", sizeof(arr + 0));//4/8printf("%d/n", sizeof(*arr));//1printf("%d/n", sizeof(arr[1]));//1printf("%d/n", sizeof(&arr));//4/8printf("%d/n", sizeof(&arr + 1));//4/8printf("%d/n", sizeof(&arr[0] + 1));//4/8printf("%d/n", strlen(arr));//6printf("%d/n", strlen(arr + 0));//6printf("%d/n", strlen(*arr));//報(bào)錯(cuò)printf("%d/n", strlen(arr[1]));//報(bào)錯(cuò)printf("%d/n", strlen(&arr));//6printf("%d/n", strlen(&arr + 1));//隨機(jī)值printf("%d/n", strlen(&arr[0] + 1));//5
  1. sizeof計(jì)算變量的長(zhǎng)度,變量可以是數(shù)組,數(shù)組元素以及指針。數(shù)組就是整個(gè)數(shù)組的大小,數(shù)組元素則是數(shù)組元素的大小,指針大小都為4/8。
  2. strlen把傳過(guò)來(lái)的參數(shù)都當(dāng)作地址,是地址就從該地址處向后遍歷找/0,不是地址當(dāng)作地址非法訪問(wèn)就報(bào)錯(cuò)。
常量字符串
char* p = "abcdef";

"abcdef"是常量字符串,用一個(gè)字符指針p指向該字符串,實(shí)質(zhì)是p存入了首字符a的地址。由于字符串在內(nèi)存中連續(xù)存放,依此特性便可以遍歷訪問(wèn)整個(gè)字符串。

char* p = "abcdef";
            
                     
             
               

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/119679.html

相關(guān)文章

  • C語(yǔ)言進(jìn)階指針進(jìn)階

    摘要:本章節(jié)在此基礎(chǔ)上,對(duì)語(yǔ)言階段指針進(jìn)行更深層次的研究。數(shù)組指針的類型由數(shù)組類型決定,先找出數(shù)組的類型去掉名就是類型。相當(dāng)于數(shù)組指針?biāo)赶驍?shù)組的數(shù)組名。數(shù)組指針指向整個(gè)數(shù)組,將其看作二維數(shù)組并解引用得到一行的首元素,從而遍歷訪問(wèn)。 ...

    浠ラ箍 評(píng)論0 收藏0
  • 玩轉(zhuǎn)指針,手撕c語(yǔ)言——(指針進(jìn)階

    摘要:函數(shù)的返回值為指針就按照字面意思,指針函數(shù)的定義顧名思義,指針函數(shù)即返回指針的函數(shù)。 目錄 前言指針與函數(shù)函數(shù)的返回值為指針作為函數(shù)參數(shù)的指針指針函數(shù)可以改變變量...

    genedna 評(píng)論0 收藏0
  • C語(yǔ)言進(jìn)階:動(dòng)態(tài)內(nèi)存管理

    摘要:釋放不完全導(dǎo)致內(nèi)存泄漏。既然把柔性數(shù)組放在動(dòng)態(tài)內(nèi)存管理一章,可見(jiàn)二者有必然的聯(lián)系。包含柔性數(shù)組的結(jié)構(gòu)用進(jìn)行動(dòng)態(tài)內(nèi)存分配,且分配的內(nèi)存應(yīng)大于結(jié)構(gòu)大小,以滿足柔性數(shù)組的預(yù)期。使用含柔性數(shù)組的結(jié)構(gòu)體,需配合以等動(dòng)態(tài)內(nèi)存分配函數(shù)。 ...

    shinezejian 評(píng)論0 收藏0
  • 三文讀透指針語(yǔ)法【中篇】@指針進(jìn)階---函數(shù)指針+函數(shù)指針數(shù)組+指向函數(shù)指針數(shù)組的指針

    摘要:三文讀透指針上篇本文將繼續(xù)介紹有關(guān)函數(shù)指針的相關(guān)內(nèi)容。在大型工程里,函數(shù)指針應(yīng)用還是挺普遍的。首先看閱讀下面兩段有趣的代碼出自語(yǔ)言陷阱與缺陷看看他們是什么意思代碼代碼函數(shù)指針數(shù)組函數(shù)指針數(shù)組,即存放函數(shù)指針的數(shù)組。 ...

    blastz 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<