C语言学习之指针的使用详解

目录
  • 一、指针概念
    • 1.指针变量
    • 2.指针类型
    • 3.二级指针
  • 二、野指针
    • 1.野指针成因
    • 2.规避野指针
  • 三、指针运算
    • 1.指针±整数
    • 2.指针-指针
    • 3.指针关系运算
  • 四、指针数组
    • 1.指针和数组
    • 2.指针数组的概念
  • 五、字符指针
  • 六、数组指针
  • 七、数组传参和指针传参
    • 1.一维数组传参
    • 2.二维数组传参
    • 3.一级指针传参
    • 4.二级指针传参
  • 八、函数指针
  • 九、函数指针数组
  • 十、回调函数

一、指针概念

在学习指针之前我们先要了解一下内存,内存是存储区域,我们可以把内存划分成一个一个的内存单元,最小的内存单元是字节

计算机将数据存储在内存中,而为了能够快速查找到所需数据,计算机会将内存进行编号,通过查找编号,可以快速查找到数据。指针是内存中一个最小单元的编号,内存单元的编号也被称为地址,指针就是地址。

平时我们说的指针通常指的是指针变量,是用来存放内存地址的变量

1个字节(byte)=8个bit(bit即比特位,由0和1组成)

在32位的机器上(X86环境),地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节。在64位的机器上(X64环境),地址是64个0或者1组成二进制序列,那地址就得用8个字节的空间来存储,所以一个指针变量的大小是8个字节。

无论何种数据类型的指针,指针的大小在32位(X86环境)平台下是4个字节,在64位(X64环境)平台下是8个字节。

1.指针变量

我们可以通过&(取地址操作符)取出变量的内存起始地址,把地址可以存放到一个变量中,这个变量就是指针变量。

*(解引用操作符又叫间接访问操作符):对指针变量进行解引用操作,通过指针变量里面的地址找到指向的内容。

#include <stdio.h>
int main()
{
	int  a = 20;
	char ch;
	int* pa = &a;//a向内存申请了4个字节的空间,所以&a的时候应该拿出第1个字节的地址
	//拿出a的第1个字节的地址放在整型指针变量pa里
	char* pc = &ch;//拿出ch的地址放在字符指针变量pc里
	printf("%p\n",&a);//%p打印的是地址
	//printf("%p\n",pa);打印出来的地址和&a打印出来的一样
	printf("%p\n",&ch);
	return 0;
}

指针变量是用来存放地址的变量,存放在指针变量中的值都被当成地址处理,同时地址是唯一标识一个内存单元的

2.指针类型

指针的类型根据你所需要的数据类型进行使用,如

  • //char* pc;指针类型是char*
  • // char** pcc;指针类型是char**
  • //int* pa;指针类型是int*
  • // double* pd;指针类型是double*
  • // …

但是要注意区分指针指向的类型和指针类型之间的区别

  • // char* pc;其中* 指pc是指针,指向的类型是char
  • // char** pcc;其中* 指pcc是指针,指向的类型是char*
  • // int* pa* 指pa是指针,指向的类型是int
  • // double* pd* 指pd是指针,指针指向的类型是double
  • // …

指针类型决定了指针进行解引用操作时访问几个字节

char* 类型的指针解引用访问1个字节;

int* 类型的指针解引用访问4个字节;

double* 类型的指针解引用访问8个字节;

例1:

#include <stdio.h>
int main()
{
	int a = 0x11223344;//用16进制表示
	int* pa = &a;
	*pa = 0;
	return 0;
}

上述代码在VS(小端存储)调试过程中,&a在内存中显示的是

执行完*pa=0;后,&a在内存中变为

将例1中的指针类型改为char* 类型,用char* 类型的指针接收a的地址

int* 和 char*类型的指针都能将int类型的a存放,因为在32位平台下,指针类型的大小都是4个字节。

#include <stdio.h>
int main()
{
	int a = 0x11223344;//用16进制表示
	char* pc = &a;
	*pc = 0;
	return 0;
}

上述代码在VS(小端存储)调试过程中,&a在内存中显示的是

执行完*pc=0;语句后,内存变化为

通过上述两个代码块执行后内存中的变化可以验证指针类型决定了指针进行解引用操作时访问几个字节

指针类型决定了指针的步长,指针加减整数的时候向前或者向后走一步走多大距离

(char*)+1------跳过一个char类型的大小,也就是向后走1个字节;

(int*)+1------跳过一个int类型的大小,也就是向后走4个字节;

(double*)+1------跳过一个double类型的大小,也就是向后走8个字节;

#include <stdio.h>
int main()
{
	int a = 0x11223344;
	int* pa = &a;
	char* pc = &a;
	printf("%p\n",pa);
	printf("%p\n",pc);
	printf("%p\n",pa+1);
	printf("%p\n",pc+1);
	return 0;
}

上述代码的运行结果为

说明指针加减整数时的步长和指针指向的类型有关

练习1:

我们可以通过一个练习对其有更好的理解:将数组arr中每个元素赋值为对应下标,arr[0]为0;arr[1]为1……

#include <stdio.h>
int main()
{
	int arr[10] = { 0 };
	int* p = arr;//p指向arr数组的首元素地址
	int i = 0;
	for(i = 0;i < 10; i++)
	{
		*(p++) = i;//将数组元素赋值;
		//后置++,对p进行解引用,赋值之后,再向后走int类型的大小,即4个字节,依次循环
	}
	for(i = 0;i < 10; i++)
	{
		printf("%d ",arr[i]);
	}
	return 0;
}

运行结果如图

3.二级指针

#include <stdio.h>
int main()
{
	int a = 10;
	int* p = &a;
	int** pp = &p;//pp就是二级指针
	*p = 20;//可以将a修改成20
	**pp = 30;//可以将a修改成30
	printf("%d\n",a);
	return 0;
}

二、野指针

野指针就是指针指向的位置是不可知的,(随机的、不正确的、没有明确限制的)

1.野指针成因

1.指针未初始化

#include <stdio.h>
int main()
{
	int* p;//p没有初始化,p就是野指针
	*p = 20;//赋值
	return 0;
}

2.指针越界访问

#include <stdio.h>
int main()
{
	int arr[10] = { 0 };
	int i = 0;
	int sz = sizeof(arr)/sizeof(arr[0]);//计算arr数组中元素个数
	int* p = arr;
	for(i = 0;i <= sz; i++)//共循环11次
	{
		*p++ = i;
	}
	return 0;
}

当p越过arr已有空间去越界访问的时候就是野指针了,之前不是野指针。

当指针指向的范围超出数组arr的范围时,p就是野指针

3.指针指向的空间释放

#include <stdio.h>
int* test()
{
	int num = 100;//num是局部变量,进函数创建,函数结束时销毁
	return &num;//返回的是栈空间的地址
}
int main()
{
	int* p = test();//接收到地址,但是地址并不指向num,不知道指向的是哪里,所以*p = 200并不知道修改的是哪里
	//虽然接收到地址,但是num已经销毁
	*p = 200;
	return 0;
}

2.规避野指针

1.指针初始化

#include <stdio.h>
int main()
{
	int a = 10;
	int* pa = &a;//明确指针
	int* pa = NULL;//当pa不知道指向哪里时,置空
	//NULL就是用来初始化指针的
	//*pa = 20;//error,在对指针置空之后不能这样使用,NULL属于系统(内核),不能访问
	return 0;
}

2.小心指针越界问题

3.指针指向空间释放,及时置NULL;

#include <stdio.h>
#include <stdlib.h>//malloc的头文件
int main()
{
	//动态申请内存空间
	int* p=(int*)malloc(40);
	//使用
	//释放
	free(p);
	p=NULL;
	return 0;
}

4.避免返回局部变量的地址,即避免返回栈空间的地址,这样可以尽量避免指针指向的空间释放这种情况。

5.指针使用之前检查有效性

三、指针运算

1.指针±整数

指针±整数是根据指针指向的数据类型大小向前或者向后走多少个字节。

  • //char* pc;pc+1就是向后走一个char类型大小的字节;
  • //int* pa;pa+1就是向后走一个int类型大小的字节;
  • //double* pd;pd+1就是向后走一个double类型大小的字节;
  • //……

在练习1中已经对其用法进行简单演示。

2.指针-指针

两个指针相减的前提是:指针指向的是同一块连续的空间,且是同一种类型的指针。

指针和指针相减的绝对值是指针之间的元素个数

#include <stdio.h>
int main()
{
	int arr[10] = { 0 };
	printf("%d\n",&arr[9]-&arr[0]);//9
	printf("%d\n",&arr[9]-&arr[0]);//-9
	return 0;
}

练习2:

模拟实现strlen,strlen函数在对字符串中的字符进行统计时,遇见’\0’停止。

#include <stdio.h>
int my_strlen(const char* arr)
{
	const char* start = arr;//将arr数组首元素地址赋给start
	const char* end = arr;
	while(*end)
	{
		end++;
	}
	return end-start;
}
int main()
{
	char arr[] = "abcdef";
	int len = my_strlen(arr);
	printf("%d",len);//6
	return 0;
}

3.指针关系运算

#include <stdio.h>
int main()
{
	int i = 0;
	int arr[10] = { 0 };
	int* p = &arr[10];
	for(p = &arr[10];p > &arr[0])
	{
		*--p = 0;//先将p向前移动4个字节,再对p赋值;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);// 全为0
	}
	return 0;
}

指针关系运算的标准规定:允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许指向数组元素的指针与指向数组第一个元素前面的那个内存位置的指针进行比较。

四、指针数组

1.指针和数组

指针和数组不是一个东西,指针是一个变量,是用来存放地址的,4/8个字节;数组能够存放一组数,是一个连续的空间,数组的大小取决于元素个数。

联系:数组名就是地址(指针);数组把首元素的地址交给一个指针变量之后,可以通过指针来访问数组。

2.指针数组的概念

//char arr[n]——字符数组:存放字符的数组

//int arr[n]——整型数组:存放整型的数组

指针数组:存放指针的数组

//char* arr[n]——字符指针数组:存放字符指针的数组

//int* arr[n]——整型指针数组:存放整型指针的数组

练习3:

通过指针数组打印a,b,c,d的值

#include <stdio.h>
int main()
{
	int a = 10;
	int b = 20;
	int c = 30;
	int d = 40;
	int* arr[4] = {&a,&b,&c,&d};
	for(i = 0;i < 4;i++)
	{
		printf("%d  ",*(arr[i]));
	}
	return 0;
}

运行结果为

练习4:

用一维数组模拟二维数组,打印出各个数组的值

#include <stdio.h>
int main()
{
	int arr1[4] = {1,2,3,4};
	int arr2[4] = {2,3,4,5};
	int* arr[2] = {arr1, arr2};//指针数组中存放的是每个数组中首元素的地址
	int i = 0;
	for(i = 0;i < 2;i++)
	{
		int j = 0;
		for(j = 0;j < 4;j++)
		{
			printf("%d  ",arr[i][j]);
			//arr[i][j]还可以写为*(arr[i]+j)或者*(*(arr+i)+j);arr是数组首元素的地址
		}
		printf("\n");
	}
	return 0;
}

运行结果为

练习5:

用指针数组打印字符串

#include <stdio.h>
int main()
{
	char* arr[4] = {"abc","bcd","cde","def"};//常量字符串
	//arr中存放的是每个字符串中首个字符的地址
	int i = 0;
	for(i = 0;i < 4;i++)
	{
		printf("%s\n",arr[i]);//%s打印字符串,只要有字符串起始地址就可以打印
	}
	return 0;
}

运行结果为

五、字符指针

在指针的类型中,我们知道有一种指针类型叫字符指针char*。

#include <stdio.h>
int main()
{
	char* pc = "abcdef";
	printf("%s\n", pc);//abcdef
	printf("%c", *pc);//a
	return 0;
}

字符指针可以存放字符串的起始地址,把字符串首元素的地址存在pc中,但这种做法不合理;"abcdef"是常量字符串,不能修改,这时让"*pc = 'w'"程序会崩,可以将char* pc = "abcdef"修改为const char* pc = "abcdef",const放在* 的左边,限制*pc,不能改变字符串内容。

练习6:

判断下列代码的输出内容;

#include <stdio.h>
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcdef";
	const char* arr3 = "abcdef";
	const char* arr4 = "abcdef";
	if(arr1 == arr2)//数组名表示数组首元素的地址,比较地址是否相同
		printf("arr1 and arr2 are same\n");
	else
		printf("arr1 and arr2 are not same\n");
	if(arr3 == arr4)
		printf("arr3 and arr4 are same\n");
	else
		printf("arr3 and arr4 are not same\n");
	return 0;
}

输出结果为

if(arr1 == arr2)if(arr3 == arr4)比较的是他们的首元素地址是否相同。

数组名是数组首元素的地址,arr1和arr2是数组,他们的首元素地址不同,所以他们不相同。

而arr3和arr4是char*类型的指针,他们指向的是常量字符串,常量字符串在内存中只保存一份,地址相同,所以arr3和arr4指向的都是a的地址。

六、数组指针

//char* pc——字符指针-指向字符的指针,存放字符变量的地址

//int* pa ——整型指针-指向整型的指针,存放整型变量的地址

//int(*p)[n]——数组指针-指向数组的指针,存放数组的地址,p是数组指针变量

数组指针在一维数组里面的应用

void print(int(*p)[5])
{
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", (*p)[i]);
	}
}
int main()
{
	int arr[5] = { 1,2,3,4,5 };
	print(&arr);//&arr取的是整个数组的地址
	return 0;
}

运行结果为

注意是数组指针也是指针,p应该先与 * 结合,再与[ ]结合, (*p)要用( )括起来

数组指针很少在一维数组中应用,一般在二维数组中应用

void print(int(*p)[5], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			printf("%d ", *( * (p + i) + j));
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
	print(&arr, 3, 5);
	return 0;
}

运行结果

数组名相当于数组首元素的地址,对于二维数组来说,首元素理解为他的第0行,p里面存的是第0行的地址,p是数组指针类型,p+1相当于向后走了5个int类型的大小,p+1指向第1行,(p+i)指向的就是第i行的地址。* (p+i) 相当于第i行的数组名; * (p+i)=p[i]。

扩展:int(*p[10])[5]——p是数组,有10个元素,每个元素都是数组指针,每个数组指针指向一个具有5个int类型的数组的地址。我们可以说p是存放数组指针的数组。

七、数组传参和指针传参

1.一维数组传参

数组传参,形参可以是数组,也可以是指针。

int arr[10] = {0}传参,他的参数用数组接收可以是int arr[]或者int arr[10];用指针接收是int* arr

int* arr[10] = {0}传参,他的参数用数组接收是int* arr[10],用指针接收是int** arr

2.二维数组传参

int arr[3][5]传参,他的参数用数组接收是int arr[3][5]或者int arr[][5],用指针接收int (*arr)[5]

3.一级指针传参

int* p传参,参数部分直接写成指针形式:int* p

4.二级指针传参

int** p传参,参数部分直接写成指针形式:int** p

八、函数指针

#include <stdio.h>
int Add(int x,int y)
{
	return x+y;
}
int main()
{
	int a = 10;
	int b = 20;
	int(*pf)(int,int)=Add;
	//int(*pf)(int,int)中,int是函数返回类型,pf是函数指针变量,(int,int)是函数的参数类型
	//int ret = Add(a,b);
	int ret = (*pf)(a,b);//输出结果是30
	//使用函数指针时,也可以省略*
	//int ret = pf(a,b);
	printf("%d",ret);
	return 0;
}

九、函数指针数组

函数指针数组:可以存放多个返回类型相同和参数相同的函数的地址。

我们通过构造一个简单的计算器来实现对函数指针数组的应用

void menu()
{
	printf("******************\n");
	printf("**1.Add    2.Sub**\n");
	printf("**3.Mul    4.Div**\n");
	printf("**0.exit        **\n");
	printf("******************\n");
}
int Add(int x, int y)//加法
{
	return x + y;
}
int Sub(int x, int y)//减法
{
	return x - y;
}
int Mul(int x, int y)//乘法
{
	return x * y;
}
int Div(int x, int y)//除法
{
	return x / y;
}
int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	int(*pf[5])(int, int) = { 0,Add,Sub,Mul,Div };//利用数组下标引用函数
	do
	{
		menu();
		printf("请选择>:");
		scanf("%d", &input);
		if (input == 0)//input为0时,直接退出计算器
		{
			printf("退出计算器\n");
			break;
		}
		if (input >= 1 && input <= 4)//判断input是否符合要求
		{
			printf("请输入两个操作数:");
			scanf("%d%d", &x, &y);
			ret = (*pf[input])(x, y);
			printf("结果为%d\n", ret);
		}
		else
		{
			printf("选择错误\n");//input不符合要求,给与提示
		}
	} while (input);
	return 0;
}

扩展:指向函数指针数组的指针int(*(*pf)[5])(int,int)=&pf

十、回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或发生时由另外的一方调用的,用于对该事件或条件进行响应。简言之,我们拿到一个函数,通过函数的地址调用一个函数,被调用的函数就被称为回调函数。

我们通过对上面那个计算器进行改写,从而让我们能够更好的理解回调函数。

void menu()
{
	printf("******************\n");
	printf("**1.Add    2.Sub**\n");
	printf("**3.Mul    4.Div**\n");
	printf("**0.exit        **\n");
	printf("******************\n");
}
int Add(int x, int y)//加法
{
	return x + y;
}
int Sub(int x, int y)//减法
{
	return x - y;
}
int Mul(int x, int y)//乘法
{
	return x * y;
}
int Div(int x, int y)//除法
{
	return x / y;
}
void calc(int(*p)(int, int))
{
	int x = 0;
	int y = 0;
	printf("请输入两个操作数:");
	scanf("%d%d", &x, &y);
	printf("%d\n", (*p)(x,y));
}
int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	int(*pf[5])(int, int) = { 0,Add,Sub,Mul,Div };
	do
	{
		menu();
		printf("请选择>:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			calc(Add);
			break;
		case 2:
			calc(Sub);
			break;
		case 3:
			calc(Mul);
			break;
		case 4:
			calc(Div);
			break;
		case 0:
			printf("EXIT");
		}
	} while (input);
	return 0;
}

把函数地址传给一个函数calc,在calc函数内部通过函数指针p调用Add时,Add就被称为回调函数。

以上就是C语言学习之指针的使用详解的详细内容,更多关于C语言指针的资料请关注我们其它相关文章!

(0)

相关推荐

  • C语言学习之指针知识总结

    目录 一.地址 二.指针与指针变量 三.指针的作用 四.初学指针时常见的错误 五.通过调用函数修改主调函数中的值 六.指针与一维数组 七.使用函数操作一维数组 八.指针变量所占字节数 九.静态数组的缺陷 十.malloc函数 十一.动态数组的构造 十二.静态内存与动态内存的对比 十三.多级指针 十四.跨函数使用内存 一.地址 内存中的最小单元是字节,一个字节对应一个编号,这里的编号就是对应字节的地址.换句话说,地址就是内存单元的编号. 二.指针与指针变量 指针与指针变量是两个不同的概念,指针是某

  • C语言详细讲解指针数组的用法

    目录 1. 指针数组定义方法 2. 指针的指针(二级指针) 3. 字符串和指针 4. 数组指针 定义方法 数组指针的用法 1. 指针数组定义方法 格式: 类型说明符 *数组名[ 元素个数 ] int *p[10]; // 定义了一个整型指针数组p,有10个元素,都是int *类型的变量 指针数组的分类: 同指针类型的分类,见上一篇 大多数情况下,指针数组都用来保存多个字符串. #include <stdio.h> int main() { char *name[5] = {"Hell

  • C语言深入浅出分析函数指针

    目录 我们先看一个代码: #include<stdio.h> void test() { printf("haha\n"); } int main() { printf("%p\n", test); printf("%p\n", &test); return 0; } 输出的是两个地址,函数名就是函数的地址 将函数的地址存起来: #include<stdio.h> void test() { printf(&quo

  • C语言常见的指针笔试题解析

    目录 笔试题1 笔试题2 笔试题3 笔试题4 笔试题5 笔试题6 笔试题7 笔试题8 在我们学习指针之后,应该在实际应用中去理解和掌握它,毕竟实践才是检验真理的唯一标准,我们以后在找工作的过程中免不了会遇到与指针相关的试题,本篇文章可以帮助我们提前了解一些常见的指针考点.在学习这篇文章之前可以根据需要对指针进行简要复习. 注:本篇文章所有代码均在X86环境下运行. 笔试题1 #include <stdio.h> int main() { int a[5] = { 1,2,3,4,5 }; in

  • Go语言学习之指针的用法详解

    目录 引言 一.定义结构体 1. 语法格式 2. 示例 二.访问结构体成员 三.结构体作为函数参数 四.结构体指针 总结 引言 Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合 结构体表示一项记录,比如保存图书馆的书籍记录,每本书有以下属性: Title :标题 Author : 作者 Subject:学科 ID:书籍ID 一.定义结构体 1. 语法格式 结构体定义需要使用 type 和 struc

  • C语言学习之指针的使用详解

    目录 一.指针概念 1.指针变量 2.指针类型 3.二级指针 二.野指针 1.野指针成因 2.规避野指针 三.指针运算 1.指针±整数 2.指针-指针 3.指针关系运算 四.指针数组 1.指针和数组 2.指针数组的概念 五.字符指针 六.数组指针 七.数组传参和指针传参 1.一维数组传参 2.二维数组传参 3.一级指针传参 4.二级指针传参 八.函数指针 九.函数指针数组 十.回调函数 一.指针概念 在学习指针之前我们先要了解一下内存,内存是存储区域,我们可以把内存划分成一个一个的内存单元,最小

  • C语言学习进阶篇之万字详解指针与qsort函数

    目录 前言 函数指针 代码一 代码二 函数指针数组 函数指针数组的用途 计算器的基本代码 函数指针实现简单的计算机 函数指针数组实现简单计算机 指向函数指针数组的指针 回调函数 简单的冒泡排序 冒泡排序的优化 qsort函数 qsort函数介绍 qsort实现冒泡排序 qsort排序结构数据 模拟实现qsort函数 写在最后 前言 前面学到了字符指针,指针数组是一个存储指针的数组,数组指针是一个指向函数的指针,数组参数和指针参数.其中不乏有很多需要注意的知识点,例如:&数组名和数组名表示的含义,

  • Go语言学习之反射的用法详解

    目录 1. reflect 包 1.1 获取变量类型 1.2 断言处理类型转换 2. ValueOf 2.1 获取变量值 2.2 类型转换 3. Value.Set 3.1 设置变量值 3.2 示例 4. 结构体反射 4.1 查看结构体字段数量和方法数量 4.2 获取结构体属性 4.3 更改属性值 4.4 Tag原信息处理 5. 函数反射 6. 方法反射 6.1 使用 MethodByName 名称调用方法 6.2 使用 method 索引调用方法 反射指的是运行时动态的获取变量的相关信息 1.

  • Go语言学习之链表的使用详解

    目录 1. 什么是链表 2. 单项链表的基本操作 3. 使用 struct 定义单链表 4. 尾部添加节点 5. 头部插入节点 6. 指定节点后添加新节点 7. 删除节点 1. 什么是链表 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的. 链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域. 使用链表结构可以避免在使用数组时需要预先知

  • C语言中二级指针的实例详解

    C语言中二级指针的实例详解 用图说明 示例代码: #include <stdio.h> int main(int argc, const char * argv[]) { // int a = 5; int *p1 = &a; //-打印地址-----地址相同--------------- printf("&a = %p\n", &a);// printf("p1 = %p\n", p1);// int **p2 = &p

  • R语言学习笔记之lm函数详解

    在使用lm函数做一元线性回归时,发现lm(y~x+1)和lm(y~x)的结果是一致的,一直没找到两者之间的区别,经过大神们的讨论和测试,才发现其中的差别,测试如下: ------------------------------------------------------------- ------------------------------------------------------------- 结果可以发现,两者的结果是一样的,并无区别,但是若改为lm(y~x-1)就能看出+1和

  • Go语言学习之数组的用法详解

    目录 引言 一.数组的定义 1. 语法 2. 示例 二.数组的初始化 1. 未初始化的数组 2. 使用初始化列表 3. 省略数组长度 4. 指定索引值的方式来初始化 5. 访问数组元素 6. 根据数组长度遍历数组 三. 访问数组元素 1. 访问数组元素 2. 根据数组长度遍历数组 四.冒泡排序 五.多维数组 1. 二维数组 2. 初始化二维数组 3. 访问二维数组 六.向函数传递数组 1. 形参设定数组大小 2. 形参未设定数组大小 3. 示例 总结 引言 数组是相同数据类型的一组数据的集合,数

  • Go语言学习之条件语句使用详解

    目录 1.if...else判断语法 2.if嵌套语法 3.switch语句 4.类型switch语句 5.fallthrough关键字使用 小结 1.if...else判断语法 语法的使用和其他语言没啥区别. 样例代码如下: // 判断语句 func panduan(a int) { if a > 50 { fmt.Println("a > 50") } else if a < 30 { fmt.Println("a < 30") } el

  • go语言结构体指针操作示例详解

    目录 指针 go指针操作 不能操作不合法指向 new函数 指针做函数的参数 数组指针 结构体指针变量 结构体成员普通变量 结构体成员指针变量 结构体比较和赋值 结构体作为函数参数 指针 指针是代表某个内存地址的值.内存地址储存另一个变量的值. 指针(地址),一旦定义了不可改变,指针指向的值可以改变 go指针操作 1.默认值nil,没有NULL常量 2.操作符“&”取变量地址,“*“通过指针(地址)访问目标对象(指向值) 3.不支持指针运算,不支持“->”(箭头)运算符,直接用“.”访问目标成

随机推荐