python 指针_指针篇 | 指针的灵活让我想起了Python
本文的題目其實有點蹭Python熱度的意思,指針確實很靈活,當然易用程度和Python還是沒得比,想要靈活使用指針,仍然要花大工夫。但一旦你感受到了指針的真諦,你也就自然能夠感受到指針的靈活了!本文通過字符串這一載體,為指針打個call。
1.數組和指針
為什么先要介紹下數組和指針,因為在C語言中,并沒有字符串類型,字符串往往是搭載在字符數組,和指針中的。因此在開篇對數組和指針的異同做個簡單的介紹。其實數組和指針我們都可以認為和int,float一樣是一種變量類型。
1.數組類型:固定大小內存塊的別名,數組名是保存該內存塊首地址的變量類型。
2.指針類型:保存某一內存的地址的變量類型。
其實聽上去好像數組名和指針沒什么區別。確實,大部分情況下,數組名的用法和指針是一樣的,如下代碼所示。
void main()
{
int i = 0;
char *p = NULL;
char buf5[128] = "ylylylylyl"; // buf
for (i=0; i
{
printf("%c ", buf5[i]);
}
p = buf5; //buf 代表數組首元素的地址
for (i=0; i
{
p = p +i;
printf("%c ", *p ) ;
}
//buf
for (i=0; i
{
printf("%c ", *(buf5+i) ) ;
}
//[] *的推導過程
// buf5[i] ===> buf5[0+i]; ==> *(buf5+i);
printf("hello....\n");
system("pause");
}
如上述代碼所示,我們可以發現數組名和指針有兩個共同點:
1.[]的本質 和*p 是一樣 ,只不過是符合程序員的閱讀習慣。
2.讀取數據時,指針和數組名的用法一致。
但需要注意的是數組名有一個特性,為常量指針,原因在于數組類型是局部變量,最終編譯器需要自動釋放內存空間,所以其首地址指向是不能變的,一旦變了就不能釋放了。而指針沒有這個限定。如下代碼所示,若是改變數組名的指向,程序是會報錯的。
{
buf5 = buf5 + 1;
buf5 = 0x11;
}
2.字符串
上述已經介紹了數組和指針的異同,接下來進入正題。我們將通過字符串,來進一步論述下數組和指針在操作時內存模型的區別。
void main61()
{
char buf[20]= "yy"; //定義并且初始化
char buf2[] = "ll";
char *p1 = "jj";
char *p2 = malloc(100);
strcpy(p2, "mm");
return ;
}
如上述代碼和對應的內存四區模型所示,可以很清晰的看到數組和指針在操縱字符串時的區別。很顯然的是指針操縱字符串將會更方便。
Note:在上述內存四區模型中,我們可以看到每個字符串后面有一個“/0”,該字符是每個字符串都會有的,表示字符串結束的標志。而基于此,需要對字符串的長度和對應的存放字符串的字符數組的長度作區分。如下代碼所示,很顯然字符數組的長度要比對應存放的字符串長度大。strlen 和 sizeof,其實sizeof求得的是計算機感知到的長度,strlen得到的是一種人類理解上的長度。
#strlen() 長度 不包括0
#sizeof() 內存塊的大小
void main()
{
int size = 0;
char buf3[] = "abcd";
int len = strlen(buf3);
printf("buf3字符的長度:%d \n", len); #輸出4
size = sizeof(buf3);
printf("buf3數組所占內存空間大小:%d \n", size); #輸出5
return ;
}
3.指針是如何高效操縱字符串的
利用指針實現字符串的拷貝。如下述代碼所示,利用指針,一句話while ( *tmpto++ = *tmpfrom++ ) ;就能實現這個功能(其余代碼都是為了代碼的接口封裝,和代碼的穩健性所存在的。)
//不要輕易改變形參的值, 要引入一個輔助的指針變量. 把形參給接過來.....
int copy_str26_good(char *from , char *to)
{
char *tmpfrom = from;
char *tmpto = to;
if ( from == NULL || to == NULL)
{
return -1;
}
while ( *tmpto++ = *tmpfrom++ ) ; //空語句
return 0;
}
int main()
{
int ret = 0;
char *from = "abcd";
char buf2[100];
ret = copy_str26_good(from, buf2);
if (ret != 0)
{
printf("func copy_str26_good() err:%d ", ret);
return ret;
}
return ret;
}
利用指針實現從對應的長字符串中,找出短字符串出現的次數。
//求字符串p中子串 abcd出現的次數
int getCount(char *mystr /*in*/, char *sub /*in*/,int *ncount)
{
int ret = 0;
int tmpCount = 0;
char *p = mystr; //不要輕易改變形參的值,因此把形參接過來
//防止程度掛掉
if (mystr==NULL || sub==NULL ||ncount==NULL)
{
ret = -1;
printf("func getCount() err:%d (mystr==NULL || sub==NULL ||ncount==NULL) \n", ret);
return ret;
}
do
{
p = strstr(p, sub);
if (p != NULL)
{
tmpCount++;
p = p + strlen(sub); //指針達到下次查找的條件
}
else
{
break;
}
} while (*p != '\0');
*ncount = tmpCount; //間接賦值是指針存在的最大意義
return ret;
}
int main()
{
int ret = 0;
char *p = "abcd111122abcd3333322abcd3333322qqq";
int count = 0;
char sub[] = "abcd";
ret = getCount(p,sub, &count);
if (ret != 0)
{
printf("func getCount() err:%d \n", ret);
return ret;
}
//若在子函數中不對輸入指針形參進行判斷,則下述代碼就會掛掉
ret = getCount(p,NULL, &count);
if (ret != 0)
{
printf("func getCount() err:%d \n", ret);
return ret;
}
printf("count:%d \n", count);
}
總之,如果你對指針操作數據時的內存模型有一個清晰的認知,那么你用起指針來將會溜的飛起。。。而且相較與python而言,掌控感更強。當然就筆者的使用經驗來說,如果你僅僅是想開發上述例子中的對應功能,或者是leetcode刷題,建議使用python。如果你對內存指針感興趣,未來又可能會從事面向設備的編程,建議在空閑時間深入學習下指針。(我在學校搞深度學習以及剛開始工作練模型的時候也沒想到我居然會慢慢的對指針這玩意這么感興趣。。。)
總結
以上是生活随笔為你收集整理的python 指针_指针篇 | 指针的灵活让我想起了Python的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python文件编码与解码_Python
- 下一篇: cassandra可视化工具_程序员绘图