主頁 > 軟體設計 > 初學者對C語言中指標的愛恨情仇

初學者對C語言中指標的愛恨情仇

2021-07-23 08:33:36 軟體設計

C語言中指標和陣列的愛恨情仇

文章目錄

  • C語言中指標和陣列的愛恨情仇
  • 一、前言
  • 二、為什么學指標
  • 三、說明
  • 四、跟我一起學
    • (一)C語言中的*和&
      • 1、C語言中為什么存在&和*
      • 2、&和*是什么?
      • 3、&(取地址運算子)和*(間接尋址運算子)的使用
    • (二)初識指標和變數
      • 1、變數
        • (1)變數如何創建
        • (2)變數如何賦值
        • (3)變數如何使用
      • 2、指標
        • (1)指標如何創建
        • (2)指標如何賦值
        • (3)指標如何使用
    • (三)指標的一些基本用法
      • 1、指標和變數的定義
      • 2、指標和變數的初始化
      • 3、指標如何作為引數
      • 4、指標如何作為回傳值
      • 5、案例1:完成swap函式,完成兩個引數交換的功能
      • 6、案例2:找到最大和第二大的值
    • (四)指標和陣列的淵源
      • 1、提前說明
      • 2、陣列和指標的簡單運用
      • 3、指標中的算術運算
        • (1)指標加上整數
        • (2)指標減去整數
        • (3)兩個指標相減
      • 4、指標做比較
      • 5、指標指向復合
      • 6、指標直接指向陣列
    • (五)指標實戰演算法題
  • 五、結尾

一、前言

你可能會有小疑問,愛什么?恨什么?

先說恨吧,相信剛學C語言的同志都恨過,

記得大一時,C語言老師上課時用的VC++6.0,記得考試時用的VC++6.0,當時真的咬牙切齒,你說能不恨嗎,

沒有代碼提示,直接勸退了!

剛考完C語言的時候,真的想過這輩子再也不碰C了,

大二下學期,學了Java,授課老師用的Eclipse,雖然老師上課手擼代碼,但是我們寫作業,考試起碼有提示呀,頓時喜歡上了,

就這樣,大學期間搞了四年的Java,

那么愛什么呢?

愛的是,我大學畢業后缺搞起C語言,做了嵌入式Linux開發,因為我非常喜歡Linux,

C語言可以直接操作硬體的,那么你可能會問,一個編程語言怎么能和硬體想關聯呢?是不是很神奇,

我一開始也不知道,后來經過在公司的一段時間內接觸了HDMI、DVI、VGA等信號的驅動知識才了解到,C語言是可以直接操作暫存器的,但是也不能直接操作,而是通過一些特定的協議規則,例如:I2C協議,

搞嵌入式還是挺有好處的,沒有Java加班多是真的,下午下班回家、周六、周日、年假基本上不加班,也沒辦法加班,因為設備是在公司,你沒辦法拿到家里來對吧,只能回家學習了,想加班的話,還得看公司,至少我們公司965,還是挺爽的,選擇生活,還是選擇其他還是看自己,

即使不愛,也得愛呀,哈哈哈哈,

二、為什么學指標

  • 1、因為不會,基本用法都不會;
  • 2、因為很想會,必須得懂;
  • 3、因為會用到,必須得學;

不會C語言的指標,你去刷個演算法題,去瞧瞧,

哈哈,記得我下定決心搞嵌入式Linux開發的時候,第一次想使用C語言去刷演算法題的時候,因為想提升一下自己的C語言的基礎,

就打開的一個最最最簡單的題:

在這里插入圖片描述
在這里插入圖片描述

給的初始代碼如下:

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* twoSum(int* nums, int numsSize, int target, int* returnSize){

}

我滴個乖乖,這簡直了,直接頭大了,沒錯,直接勸退了,

再來看一下Java版的:

class Solution {
    public int[] twoSum(int[] nums, int target) {

    }
}

哎,好爽快呀,

你就說吧,你不會指標,你怎么去用C語言刷演算法題?????
在這里插入圖片描述

三、說明

本篇文章不長篇大論的研究指標背后的原理,因為博主還沒到這地步,只是簡單的總結一下我段時間學到的技巧用法等,

四、跟我一起學

(一)C語言中的*和&

參考我其他博文中的一段話

1、C語言中為什么存在&和*

C語言中大名鼎鼎的“指標”,想必你肯定聽說過吧,
沒錯,C語言中的&和*就是為了指標而誕生的,

指標說白了就是直接/間接的操作(取/存)存盤中的地址中的資料,

試想一下,如果沒有&和*的存在,你可能每天都在為計算和尋找某個變數在哪里而發愁呢!

有了&和*之后,就不需要你手動的去計算記憶體中的地址,

2、&和*是什么?

&取地址運算子;
*間接尋址,也可以稱為取值運算子,這樣就好理解了運算子;

&的作用:如果想找到變數的地址,可以使用&(取地址)運算子,

*的作用:如果你學過鏈表,你經常會用到:

p->q;

那么p就是指向q的地址,

如果你學過計算機組成原理或者作業系統,里面的暫存器的尋址方式,就有間接尋址方式,

間接尋址方式:說白了就是取這個地址指向的地址的值,

如果有一個變數p,那么p就是取p指向地址的值,

3、&(取地址運算子)和*(間接尋址運算子)的使用

int i; 是變數

int *pi;是指標

 int i, *pi;
 char c,*pc;

例子:

#include <stdio.h>

int main()
{
	int i, *pi;
	char c,*pc;
		
	//初始化i為10
	i = 10;

	//初始化c為‘a’字符
	c = 'a';

	//把pi指向i的地址
	pi = &i;

	//把pc指向c的地址
	pc = &c;

	printf("i=%d;c=%c\n",*pi,*pc);

	//做一些基本處理
	*pi = *pi + 100;

	printf("*pi+100=%d\n",*pi);

	
	printf("pi addr=%p;i addr=%p;pc addr=%p;c addr=%p\n",pi,&i,pc,&c);
	
	

	return 0;
}

執行結果:

i=10;c=a
*pi+100=110
pi addr=0x7ffe76034684;i addr=0x7ffe76034684;pc addr=0x7ffe76034683;c addr=0x7ffe76034683

(二)初識指標和變數

1、變數

(1)變數如何創建

zhenghui@zhlinux:~/codeProject/20210719$ cat test1.c -n 
     1	#include <stdio.h>
     2	
     3	int main()
     4	{
     5	
     6	
     7		//定義int型別的變數
     8		int i1,i2,i3;
     9		//定義double型別的變數
    10		double d1,d2,d3;
    11	
    12		return 0;
    13	}
zhenghui@zhlinux:~/codeProject/20210719$ 

如上所示代碼中的【資料型別 空格 變數名 ;】輕輕松松就定義出來了1-N個變數,

(2)變數如何賦值

        //初始化變數
        i1 = 5;
        i2 = 2;
        i3 = 1;

公式:【變數名 = 值;

意思是把什么內容保存到什么變數中,

你是不是有疑問了,區區一個小小滴變數這是如何保存的呢?別急,繼續看吧騷年,

(3)變數如何使用

zhenghui@zhlinux:~/codeProject/20210719$ 
zhenghui@zhlinux:~/codeProject/20210719$ cat test1.c 
#include <stdio.h>
int main()
{
	//定義int型別的變數
	int i1,i2,i3;
	//初始化變數
	i1 = 5;
	i2 = 2;
	i3 = 1;
	
	printf("i1=%d,i2=%d,i3=%d\n",i1,i2,i3);
	return 0;
}
zhenghui@zhlinux:~/codeProject/20210719$ zhenghui@zhlinux:~/codeProject/20210719$ 
zhenghui@zhlinux:~/codeProject/20210719$ 
zhenghui@zhlinux:~/codeProject/20210719$ gcc test1.c 
zhenghui@zhlinux:~/codeProject/20210719$ 
zhenghui@zhlinux:~/codeProject/20210719$ ./a.out 
i1=5,i2=2,i3=1
zhenghui@zhlinux:~/codeProject/20210719$ 

2、指標

(1)指標如何創建

 //定義int型別的指標
 int *p1,*p2,*p3;

(2)指標如何賦值

//定義int型別的變數
int i1,i2,i3;

//初始化變數
i1 = 5;
.......

//定義int型別的指標
int *p1,*p2,*p3;

//賦值
p1 = &i1;

等等

請留步,這里說一下,

指標,其實就是存的地址,

不信可以使用printf大法看看:

zhenghui@zhlinux:~/codeProject/20210719$ 
zhenghui@zhlinux:~/codeProject/20210719$ cat test2.c 
#include <stdio.h>

int main()
{
	//定義int型別的變數
	int i1,i2,i3;

	//初始化變數
	i1 = 5;
	i2 = 2;
	i3 = 1;

	printf("i1=%d,i2=%d,i3=%d\n",i1,i2,i3);

	//定義int型別的指標
	int *p1,*p2,*p3;

	//賦值
	p1 = &i1;

	//列印
	printf("p1=%p,&i1=%p\n",p1,&i1);
	return 0;
}
zhenghui@zhlinux:~/codeProject/20210719$ 
zhenghui@zhlinux:~/codeProject/20210719$ ./a.out 
i1=5,i2=2,i3=1
p1=0x7ffde7e3f364,&i1=0x7ffde7e3f364
zhenghui@zhlinux:~/codeProject/20210719$ 

可以看到,我用p1=&i1,列印的結果是相同的,所以可以得到結論,

一個錯誤的示范:

int *p1;
p1 = 10;

我在沒具體學習指標的時候,就這樣做過,

編譯的時候:

所以:

  • 指標變數只能接收某個記憶體中的地址;
  • 只能把地址賦值給指標變數,
zhenghui@zhlinux:~/codeProject/20210719$ 
zhenghui@zhlinux:~/codeProject/20210719$ gcc test2.c 
test2.c: In function ‘main’:
test2.c:23:5: warning: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
   23 |  p2 = 123;
      |     ^
zhenghui@zhlinux:~/codeProject/20210719$ 

(3)指標如何使用

這里只需要學會*&就行了,其余的暫時可以不用管,

(三)指標的一些基本用法

1、指標和變數的定義

//變數定義
int i,j,k;

//指標的定義
int *pi,*pj,*pk;

2、指標和變數的初始化

//變數定義
int i,j,k;

//指標的定義
int *pi,*pj,*pk;


//變數的初始化
i = 10;
j = 100;
k = 1000;

//指標的初始化
pi = &i;
pj = &j;
pk = &k;

如果你還不知道&和*的用法和作用,可以參考我這篇:
《C語言中的&和*》

3、指標如何作為引數

#include <stdio.h>

void maxV(int a,int b,int *max)
{
	if( a > b)
	{
		*max = a; 
	}else
	{
		*max = b;
	}
}

int main()
{
	//變數定義
	int i,j,k;

	//指標的定義
	int *pi,*pj,*pk;


	//變數的初始化
	i = 10;
	j = 100;
	k = 1000;

	//指標的初始化
	pi = &i;
	pj = &j;
	pk = &k;

	int max;

	maxV(i,j,&max);

	printf("最大的數是:%d\n",max);
	
	return 0;
}

結果:

最大的數是:100

4、指標如何作為回傳值

#include <stdio.h>

void maxV(int a,int b,int *max)
{
        if( a > b)
        {
                *max = a;
        }else
        {
                *max = b;
        }
}

int *maxV2(int *a,int *b)
{
        return *a > *b ? a : b;
}

int main()
{
        //變數定義
        int i,j,k;

        //指標的定義
        int *pi,*pj,*pk;


        //變數的初始化
        i = 10;
        j = 100;
        k = 1000;

        //指標的初始化
        pi = &i;
        pj = &j;
        pk = &k;

        int max;

        maxV(i,j,&max);

        printf("最大的數是:%d\n",max);


        printf("最大的數是:%d\n",*maxV2(&j,&k));

        return 0;
}

結果:

最大的數是:100
最大的數是:1000

5、案例1:完成swap函式,完成兩個引數交換的功能

zhenghui@zhlinux:~/codeProject/11指標$ 
zhenghui@zhlinux:~/codeProject/11指標$ cat swap.c 
#include <stdio.h>

void swap(int *p,int *q)
{
	int temp = *p;
	*p = *q;
	*q = temp;
}

int main()
{
	
	int a=10;
	int b=20;

	swap(&a,&b);

	printf("a=%d,b=%d\n",a,b);

	return 0;
}
zhenghui@zhlinux:~/codeProject/11指標$ 
zhenghui@zhlinux:~/codeProject/11指標$ 
zhenghui@zhlinux:~/codeProject/11指標$ ./a.out 
a=20,b=10
zhenghui@zhlinux:~/codeProject/11指標$ 

6、案例2:找到最大和第二大的值

題目如下:
在這里插入圖片描述
方法一:兩次回圈

第一次:找出最大的值,然后記錄下來最大值的位置;
第二次查找的時候把最大值的位置的資料給清空,繼續尋找最大的值,那么這一次的最大的值就是第二大的,

#include <stdio.h>
#define ARRAY_SIZE(array) ((int) (sizeof(array) / sizeof(array[0]) ))

/*
 *查找最大的值和第二大的值
 * */
void find_tow_largest(int a[],int n,int *largest,int *second_largest)
{

        //1、找到最大的值
        *largest = a[0];
        //記錄下來最大的值的位置
        int maxIndex = 0;

        for(int i = 1;i<n;i++)
        {
                if(*largest < a[i])
                {
                        *largest = a[i];

                        maxIndex = i;
                }
        }

        //2、找第二大的值

        //把最大的值變成最小的值
        a[maxIndex] = -1;
        *second_largest = a[0];

        for(int i = 1;i<n;i++)
        {
                if(*second_largest < a[i])
                {
                        *second_largest = a[i];
                }
"find_tow_larget.c" 54L, 863C                                                              31,2-9       頂端
                        *largest = a[i];

                        maxIndex = i;
                }
        }

        //2、找第二大的值

        //把最大的值變成最小的值
        a[maxIndex] = -1;
        *second_largest = a[0];

        for(int i = 1;i<n;i++)
        {
                if(*second_largest < a[i])
                {
                        *second_largest = a[i];
                }
        }

}

int main()
{
        int a[] = {1,5,2,4,7,5,8,234};

        int n = ARRAY_SIZE(a);

        int largest,second_largest;

        find_tow_largest(a,n,&largest,&second_largest);

        printf("最大的是:%d,第二大的是:%d\n",largest,second_largest);

        return 0;
}

執行結果:

zhenghui@zhlinux:~/codeProject/11指標$ vim find_tow_larget.c
zhenghui@zhlinux:~/codeProject/11指標$
zhenghui@zhlinux:~/codeProject/11指標$
zhenghui@zhlinux:~/codeProject/11指標$ gcc find_tow_larget.c
zhenghui@zhlinux:~/codeProject/11指標$
zhenghui@zhlinux:~/codeProject/11指標$ ./a.out
最大的是:234,第二大的是:8
zhenghui@zhlinux:~/codeProject/11指標$

方法2:排序

可以利用陣列的排序來做,任何排序都可以,

這里選用插入排序來做,

zhenghui@zhlinux:~/codeProject/11指標$
zhenghui@zhlinux:~/codeProject/11指標$ cat find_tow_larget.c
#include <stdio.h>
#define ARRAY_SIZE(array) ((int) (sizeof(array) / sizeof(array[0]) ))

/*
 *查找最大的值和第二大的值
 * */
void find_tow_largest(int a[],int n,int *largest,int *second_largest)
{

	//1、找到最大的值
	*largest = a[0];
	//記錄下來最大的值的位置
	int maxIndex = 0;

	for(int i = 1;i<n;i++)
	{
		if(*largest < a[i])
		{
			*largest = a[i];

			maxIndex = i;
		}
	}

	//2、找第二大的值

	//把最大的值變成最小的值
	a[maxIndex] = -1;
	*second_largest = a[0];

	for(int i = 1;i<n;i++)
	{
		if(*second_largest < a[i])
		{
			*second_largest = a[i];
		}
	}

}

/*
 *使用排序查找最大的值和第二大的值
 * */
void find_sort_tow_largest(int a[],int n,int *largest,int *second_largest)
{

	//1、初始化
	for(int i = 1;i<n;i++)
	{
		if(a[i-1] > a[i])
		{
			int j = i - 1;
			int temp = a[i];

			while(j > -1 && temp < a[j])
			{
				a[j+1] = a[j];
				j--;
			}

			a[j+1] = temp;
		}
	}

	*largest = a[n-1];
	*second_largest = a[n-2];

}



int main()
{
	int a[] = {1,5,2,4,7,5,8,234};

	int n = ARRAY_SIZE(a);

	int largest,second_largest;

	//find_tow_largest(a,n,&largest,&second_largest);
	find_sort_tow_largest(a,n,&largest,&second_largest);

	printf("最大的是:%d,第二大的是:%d\n",largest,second_largest);

	return 0;
}

結果:

zhenghui@zhlinux:~/codeProject/11指標$ ./a.out
最大的是:234,第二大的是:8
zhenghui@zhlinux:~/codeProject/11指標$

(四)指標和陣列的淵源

1、提前說明

為了更好的說明指標和陣列的情況,本文假設你最起碼已經會簡單的使用陣列了,

下文中所使用的陣列都是:int a[] = {10,20,30,40,50,60,70,80,90,100}

如下圖所示:

在這里插入圖片描述

我們宣告陣列a和指標p如下:

 int a[10] = {10,20,30,40,50,60,70,80,90,100}, *p;

2、陣列和指標的簡單運用

int a;只是存放的一個數,陣列中而是存放的一組數;

那么我們可以把某個變數的地址賦值給某個指標變數,那么陣列可不可以呢?

當然是可以的:

zhenghui@zhlinux:~/codeProject/20210720$ ./a.out 
a[0]=1,p=10 
zhenghui@zhlinux:~/codeProject/20210720$ 
zhenghui@zhlinux:~/codeProject/20210720$ 
zhenghui@zhlinux:~/codeProject/20210720$ cat test1.c 
#include <stdio.h>

int main()
{

	int a[10] = {10,20,30,40,50,60,70,80,90,100}, *p;

	p = &a[0];

	printf("a[0]=%d,p=%d \n",a[0],*p);
	
}
zhenghui@zhlinux:~/codeProject/20210720$ 

當我們把a[0]的地址賦值給p的時候,那么就相當于p指向了陣列中a[0]處這個數值的地址,如下圖所示:

在這里插入圖片描述

3、指標中的算術運算

算術運算是什么?

就是從小就會的,加法、減法、乘法、除法,

C語言中的指標支持三種格式(只有三種,只能三種)的指標算術運算,

分別是:

  • 指標加上整數
  • 指標減去整數
  • 兩個指標相減

下面來分別介紹一下陣列中的指標怎么加減,

(1)指標加上整數

實驗代碼修改如下:

zhenghui@zhlinux:~/codeProject/20210720$ cat test1.c 
#include <stdio.h>

int main()
{

	int a[10] = {10,20,30,40,50,60,70,80,90,100}, *p;

	p = &a[0];

	printf("a[0]=%d, *(p + 1)=%d \n",a[0], *(p+1) );
	
}
zhenghui@zhlinux:~/codeProject/20210720$ 

你猜猜(*p+1)會列印什么,

  • 老王說:我猜是11;
  • 老李說:我猜會報錯,指標怎么能做加法呢!;

看看是誰說的對:

zhenghui@zhlinux:~/codeProject/20210720$ gcc test1.c 
zhenghui@zhlinux:~/codeProject/20210720$ 
zhenghui@zhlinux:~/codeProject/20210720$ ./a.out 
a[0]=10, *(p + 1)=20 
zhenghui@zhlinux:~/codeProject/20210720$ 

居然是20,

為什么是20呢,是不是很納悶,

現在可以嘗試猜想一下,

這個*(p+1) = 20的話,那么這個+1的操作很明擺著就是向前移動了一個位置呀,變成了a[1],

驗證一下:

zhenghui@zhlinux:~/codeProject/20210720$ 
zhenghui@zhlinux:~/codeProject/20210720$ cat test1.c 
#include <stdio.h>

int main()
{

	int a[10] = {10,20,30,40,50,60,70,80,90,100}, *p;

	p = &a[0];

	printf("a[0]=%d, *(p + 1)=%d \n",a[0], *(p+1) );

	printf("a[1] addr=%p, *(p+1) addr=%p \n",&a[1], (p+1) );
	
}
zhenghui@zhlinux:~/codeProject/20210720$ 

通過列印a[1]和p+1的地址,還真的是一樣的地址,那么就證明了我們的猜想,如果指標指向陣列的話,那么加N就等于是向前移動了幾個位置,

zhenghui@zhlinux:~/codeProject/20210720$ ./a.out 
a[0]=10, *(p + 1)=20 
a[1] addr=0x7fff953b17b4, *(p+1) addr=0x7fff953b17b4 
zhenghui@zhlinux:~/codeProject/20210720$ 

(2)指標減去整數

有了前面加整數的鋪墊,不難想象,減去一個整數,肯定就是向后移動了幾個位置,

zhenghui@zhlinux:~/codeProject/20210720$ cat test1.c 
#include <stdio.h>

int main()
{

	int a[10] = {10,20,30,40,50,60,70,80,90,100}, *p;

	p = &a[0];

	//+5
	p = p + 5;
	
	printf("(p + 5)之后=%d \n",*p);

	//-2
	p = p - 2;
	
	printf("(p + 5 - 2)之后=%d \n",*p);


}

運行結果如下:

zhenghui@zhlinux:~/codeProject/20210720$ ./a.out 
(p + 5)之后=60 
(p + 5 - 2)之后=40 
zhenghui@zhlinux:~/codeProject/20210720$ 

(3)兩個指標相減

修改測驗代碼如下:

zhenghui@zhlinux:~/codeProject/20210720$ cat test1.c 
#include <stdio.h>

int main()
{

	int a[10] = {10,20,30,40,50,60,70,80,90,100}, *p, *q;

	p = &a[2];

	q = &a[8];

	
	printf("p=%d,q=%d,(p - q)之后=%ld \n", *p, *q,(p - q) );
	printf("p=%d,q=%d,(q - p)之后=%ld \n", *p, *q,(q - p) );

}
zhenghui@zhlinux:~/codeProject/20210720$ 

運行結果:

zhenghui@zhlinux:~/codeProject/20210720$ ./a.out 
p=30,q=90,(p - q)之后=-6 
p=30,q=90,(q - p)之后=6 
zhenghui@zhlinux:~/codeProject/20210720$ 

4、指標做比較

指標和指標之間也可以使用:<、>、<=、>=、==、!=來做比較,但是只有在相同的陣列中做比較才有意義,因為陣列中的指標做比較的話,會依賴于同一陣列中的元素的相對位置,

代碼修改如下:

zhenghui@zhlinux:~/codeProject/20210720$ cat test1.c 
#include <stdio.h>

int main()
{

	int a[10] = {10,20,30,40,50,60,70,80,90,100}, *p, *q;

	p = &a[2];
	q = &a[8];

	printf("(p > q)之后=%d \n",(p > q) );
	printf("(q < p)之后=%d \n",(q > p) );

}
zhenghui@zhlinux:~/codeProject/20210720$ 

結果:

zhenghui@zhlinux:~/codeProject/20210720$ gcc test1.c  && ./a.out 
(p > q)之后=0 
(q < p)之后=1 

5、指標指向復合

這個是c99中的一個特性,

我們之前是先創建一個陣列,然后用指標再指向陣列的第一個元素,以此達到目的,

這樣做是很不方便的,那么接下來的操作,就是可以為了簡化這個操作,減少一些麻煩,

int *p1 = (int []){1,2,3,4,5,6};

我們使用的時候,也是一樣用就可以了:

printf("p1 + 1 =%d \n",*(p1+1));

6、指標直接指向陣列

廢話不多說,直接上代碼:

zhenghui@zhlinux:~/codeProject/20210720$ cat test1.c 
#include <stdio.h>

int main()
{

	int a[10] = {10,20,30,40,50,60,70,80,90,100}, *p, *q;

	p = a;
	
	printf("p+1=%d \n",*(p+1));	

}
zhenghui@zhlinux:~/codeProject/20210720$ 
zhenghui@zhlinux:~/codeProject/20210720$ gcc test1.c && ./a.out 
p+1=20 
zhenghui@zhlinux:~/codeProject/20210720$ 

(五)指標實戰演算法題

學習完了C語言的指標,再一次信心滿滿的打開了
https://leetcode-cn.com/problems/two-sum/submissions/
這道演算法題,

現在Ubuntu的vim寫了一下:

#include <stdio.h>

int* twoSum(int* nums, int numsSize, int target, int* returnSize){

        int *res = (int[2]){};

        for(int i = 0;i<numsSize;i++)
        {

                for(int j = 1;j<numsSize;j++)
                {
                        if(i != j && (nums[i] + nums[j] == target))
                        {
                                *(res) = i;
                                *(res+1) = j;
                                *returnSize = 2;
                                return res;
                        }
                }
        }



        return res;
}

int main()
{

        int *nums = (int[]){2,7,11,15};
        int numsSize = 4;
        int target = 9;
        int returnSize;

        int *result = twoSum(nums,numsSize,target,&returnSize);

        printf("returnSize=%d,result1=%d,result2=%d \n",returnSize,*result,*(result+1));

}

運行:

zhenghui@zhlinux:~/codeProject/20210720$ gcc test2.c && ./a.out 
returnSize=2,result1=0,result2=1 
zhenghui@zhlinux:~/codeProject/20210720$

好滴很,沒有毛病,

放到力扣試試:

在這里插入圖片描述
一遍過,哈哈哈,挺開心的,

開心的是這是我用指標寫過最長的C語言代碼了,

開心的是第一次用指標寫了一個程式,

剛好對比一下,以前我用Java寫的:
在這里插入圖片描述

不得不說C語言的優勢就一下子體現出來了,

時間上的問題不是大問題,只是本次使用了兩層for回圈來處理的,時間會久一些,

五、結尾

現在高興還太早,只是初出茅廬,會了皮毛,簡單的使用,

C語言高級的地方在于記憶體的管理,如何動態的分配記憶體,管理記憶體,如何動態的分配字串,分配陣列,釋放存盤空間等等,還有一大把的基礎知識帶研究,

下次繼續研究,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/289649.html

標籤:其他

上一篇:被蘋果工程師發現 Bug,Cassandra 4.0 暫停發布

下一篇:被公司裁員后,我爬取了11個領域的 “加盟店“ 資訊,為自主創業做準備!【附11個Excel表格】

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more