微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C语言知识点 -- 2

C语言知识点 – 2


一、函数

1.数组传参

数组在传参是,传递的是首元素的地址,而不是整个数组;
数组传参时不能在函数内计算数组大小,只能由外部传进来。
代码如下:

void Test(int arr[], int sz)
//相当于void Test(int* arr, int sz)
{
	int size = sizeof(arr) / sizeof(arr[0]);
	//由于arr是数组的地址,sizeof(arr)计算的就是指针的大小
	//因此数组传参时不能在函数内计算数组大小,只能由外部传进来
}

2.静态库

使用别人的函数模块,只包含.h文件,不暴露.c文件
具体操作如下:
1.编辑好函数后,生成静态库,右键点击项目 – 属性 – 常规 – 配置类型 – 应用程序 – 静态库;

在这里插入图片描述


2.点击生成解决方案,生成.lib文件,在DeBug文件夹中;

在这里插入图片描述


3.拷贝到需要使用的工程中,添加文件 – 现有项 – __.h文件,然后在工程中包含.h文件
4.导入静态库:#pragma comment(lib, “binary_search.lib”).

#include "binary_search.h"//包含头文件
#pragma comment(lib, "binary_search.lib")//导入静态库

3.函数递归

函数每递归一次,就建立一个栈帧。
1.求n的阶乘

int factorial(int x)
{
	if (x <= 1)
	{
		return 1;//若n小于等于1,则返回1
	}
	else
	{
		return x * factorial(x - 1);//若n大于1,则递归调用
	}

}

2.斐波那契数

int fib(int x)
{
	if (x <= 2)//若n小于等于2,则返回1
	{
		return 1;
	}
	else
	{
		return fib(x - 1) + fib(x - 2);//若n大于2,则递归调用
	}

3.求字符串长度

int my_strlen(char* str)
{
	if ('\0' == *str)
	{
		return 0;//若第一个字符为\0,就返回0
	}
	else
	{
		return 1 + my_strlen(str + 1);//若第一个字符不是\0,就递归调用
	}

4.字符串反转
实现:将参数字符串中的字符反向排列,不是逆序打印。

void reverse_string(char* arr)
{
	int len = strlen(arr);//字符串长度
	char tmp = *arr;//tmp为第一个字符
	*arr = *(arr + len - 1);//第一个字符变为最后一个字符
	*(arr + len - 1) = '\0';//最后一个字符先赋值\0
	if (strlen(arr + 1) >= 2)//如果arr+1指向的字符串长度大于等于2,就递归调用
		reverse_string(arr + 1);

	*(arr + len - 1) = tmp;//最后将第一个字符给到最后一个的位置
}
//fbcde\0    tmp = a  -->  fedcba
//fecd\0\0   tmp = b  -->  fedcb\0
//fed\0\0\0  tmp = c  -->  fedc\0\0

二、数组

1.数组在内存中的存放

数组在内存中是连续存放的。

在这里插入图片描述

2.二维数组的初始化

二维数组如果初始化,行可以省略,列不能省略,根据初始化内容来确定行数。

int arr[][3] = {1,2,3,4,5};
int arr[][2] = {{1, 2}, {3,4}};

3.二维数组行和列的计算

int arr[][3] = {1,2,3,4,5};
int row = sizeof(arr) / sizeof(arr[0]);
int col = sizeof(arr[0]) / sizeof(arr[0][0]);

4.数组名

数组名是首元素的地址,但是有两个例外:
1.sizeof(数组名)计算的是整个数组的大小,此时数组名代表整个数组;
2.&数组名,取到的是整个数组的地址。

三、操作符

1. / 和 %

float a = 5 / 4;//要想/结果是浮点数,/两边必须有一个是浮点数,否则结果就是整数
float b = 5.0 / 4;

除了%两边都需要为整数外,其他的算术运算符两边可以是整数或浮点数。

2.原码、反码、补码

正整数的原码、反码、补码都是一样的;
负整数的反码是原码除了符号位外按位取反,补码是反码加一;

3.移位操作符

左移操作符<< : 操作数为二进制整数,左边抛弃,右边补0;
右移操作符>> : 算数右移:左边用符号位填充,右边丢弃(vs为算术右移);
逻辑右移:左边补0;右边丢弃。

4.位操作符

都是对补码进行运算,操作数必须为整数;
& : 按位与;
| :按位或;
^ :按位异或。

不创建临时变量,实现两数的交换:

a = a ^ b;
b = a ^ b;//b = a ^ b ^ b,自己异或为0,a和0异或为a
a = a ^ b;

求二进制数中1的个数:
1.循环右移法

int Count1(int n)
{
	int i = 0;
	int count = 0;
	for (i = 0; i < 32; i++)
	{
		if (1 == ((n >> i) & 1))
		{
			count++;
		}
	}
	return count;
}

2.公式法

//n = n & (n - 1)这个表达式每次会减少一个二进制数n中的1
int Count1(int n)
{
	int count = 0;
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
	return count;
}

在这里插入图片描述

5.单目操作符

! :逻辑反操作;
:按位取反;
(类型) :强制类型传唤。

一个数的二进制位取反:

在这里插入图片描述


打印出来是原码。

6.整型提升

C的算术型运算总是至少以缺省整形的精度来进行的,为获得这个精度,表达式中的字符型和短整型操作数在计算之前被转换为普通整形,这就叫做整型提升。

规则:有符号数的整型提升按照符号位来,无符号数直接补0。

char a = -1;
//a的二进制补码为11111111,符合号为为1,则整型提升后前面的位全部补1
//结果为:11111111111111111111111111111111

实例1:

int main()
{
	char a = 0xb6;
	short b = 0xb600;
	int c = 0xb6000000;
	if(a == oxb6)
		printf("%a");
	if(b == oxb600)
		printf("b");
	if(c == 0xb6000000)
		printf("c");
	return 0;
}

由于 == 也是运算,所以a、b均发生了整型提升,而a和b的符号位均为1,整型提升后为负数,其补码就变了,而c是整形,不需要整型提升,所以结果输出c。

实例2:

int main()
{
	char c1 = 3;//赋值也是运算符
	//3的补码:00000000000000000000000000000011
	//c1中只能存8位:000000011
	char c2 = 127'
	//127 : 00000000000000000000000001111111;
	//c2 : 01111111
	char c3 = c1 + c2;
	//发生整型提升
	//c1 : 00000000000000000000000000000011
	//c2 : 00000000000000000000000001111111
	//相加:00000000000000000000000010000010
	//c3 : 10000010
	printf("%d", c3);
	//以%d形式打印,又要整型提升
	//补码:11111111111111111111111110000010b
	//反码:11111111111111111111111110000001b
	//原码:00000000000000000000000001111110b  --  -126d
}
//最终打印结果为 -126

原文地址:https://www.jb51.cc/wenti/3281066.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐