【牛客网】JZ65:不用四则运算符实现两数相加
[TOC] 问题来源 牛客网数据结构题目👉JZ65 题目要求如图 思考 不能使用四则运算,根据过往的学习经历,我唯一能想到的就是位操作符和移位操作符 例:使用位操作符进行int变量交换 位操作符的使用 先来回顾一下位操作符的作用 位操作符操作的是整形的二进制位,它的操作数是2,比较两个整型的二进制位 &按位与:对应的二进制 全为1才是1,否则0 |按位或:对应的二进制 有1为1,全为0才为0 ^按位异或:相同为0,不同为1 比较一下正常的二进制相加和按位异或,发现按位异或是没有进位的相加 原本应该是010,但是按位异或后是000 1+1需要进位的1并没有进到下一位里去 而使用按位与操作符,我们可以得到这两个数相加需不需要进位 1234560 0 10 0 1//按位与-全1为10 0 1//<< -左移1位0 1 0 这时候将按位与之后的结果和按位异或相加,就是我们的答案了 但是题目要求不能使用加减 再将按位与的结果0 1 0与 按位异或结果0 0 0进行按位与 得到0 0 0 ,代表无需进位 这时候将0 1 0与0 0 0...
【C语言】动态内存管理(详解malloc/calloc/realloc)
[TOC] 直入主题,**动态内存管理!**🕵️♂️ 1.为什么会有动态内存分配? 我们一般使用以下两种方式开辟内存 12int a = 20;//在栈空间上开辟四个字节char arr[10] = {0};//在栈空间上开辟10个字节的连续空间 但是上述的开辟空间的方式有两个特点: 空间开辟大小是固定的。 数组在声明的时候,必须指定数组的长度,它所需要的内存在编译时分配。 但是对于空间的需求,不仅仅是上述的情况。有些时候,我们并不能提前知道需要的空间大小,而部分编译器并不支持变长数组。这时候以数组的方式开辟连续空间的方法就有点不适用了。 其次,全局变量/局部变量是存放在栈区里面的。如果存放的变量太多,就会出现栈溢出的错误。 这时候就轮到动态内存管理上场了! 2.动态内存函数 2.1 malloc 12#include <stdlib.h>//malloc的头文件void* malloc (size_t...
【C语言】自定义类型(详解)
[TOC] 在C语言中,有几个比较特殊的自定义类型:结构体、枚举、联合 本篇博客,就让我们来认识一下这些自定义类型吧!😶 1.结构体 结构体是一些值的集合,结构体的每个成员可以是不同类型的变量 1.1结构体的声明 以个人信息为例,有姓名、性别、年龄、身高等几个元素。可以定义结构体如下 1234567struct Stu{ char name[20]; char sex[5]; int age; int hight;}s2, s3, s4;//s2,s3,s4全局变量 1.2特殊声明 在声明结构体的时候,可以不完全声明 12345678910111213struct{ char c; int a; double d;}sa;struct{ char c; int a; double...
【C语言】常用的字符串函数和内存函数
[TOC] 今天我们来学习一些新的字符串函数和内存函数,了解它们背后运行的原理,并完成部分函数的自我实现😘 1.字符串函数 1.1 strlen 这个函数我们已经很熟悉了,它的作用是计算字符串的大小,以\0作为结尾 模拟实现如下: 123456789101112131415161718192021//1.strlen模拟实现int my_strlen(char* p){ assert(p); int count = 0; while (*p) { count++; p++; } return count;}int main(){ char arr[] = { "abcdef" }; int sz = my_strlen(arr); printf("sz=%d\n", sz); return 0;} assert:断言,库函数,用于判断指针是否为空,若为空会报错 1.2...
【C语言】指针进阶第五站,函数指针
[TOC] 指针进阶第五站🚏:函数指针 点进我的主页,可以回顾前四站的内容哦~ 1函数指针 函数也有自己的地址,函数名/&函数名 就是函数的地址 1.1基本形式 在数组指针的学习中我们了解到 12int arr[5];int (*pa)[5] = &arr;//pa是数组指针 指针变量pa的类型是int(*)[5] 那么函数指针的形式是怎样的呢? 123456789void test(char* str){}int main(){ void (*pt)(char*) = test; //pt是一个函数指针 return 0;} pt的类型是void (*)(char*) 下面哪个代码有能力存放函数的地址呢? 12void (*pfun1)();void *pfun2(); 答:pfun1可以存放 pfun1先和*结合,说明pfun1是指针,指针指向的是一个函数,指向的函数无...
【C语言】指针进阶终点站,回调函数和qsort
[TOC] 嘟嘟嘟,指针进阶的公交车到终点站🚏啦! 这一站我们将学习回调函数、qsort的使用以及模拟实现 1.回调函数 定义: 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一 个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该 函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或 条件进行响应。 在上篇博客函数指针数组里,提到了一个计算器的代码 在这里就能用到我们的回调函数,通过一个新的calc函数来调用计算函数,同样达到了避免switch/case语句重复的目的 不过今天我们的学习重点的内容不在这里,而是一个全新的函数:qsort 2.qsort函数 qsort函数又称 快速排序函数 2.1void*指针 1void* p = &a; void* 是一种无类型的指针,无具体类型的指针 void* 的指针变量可以存放任意类型的地址 void* 的指针不能直接进行解引用操作 void*...
【C语言】指针进阶第四站,数组/指针的传参问题
[TOC] 朋友们,到站啦! 指针进阶第四站🚏,传参问题 0.引例 自定义函数里形参的类型,要和函数调用中传过去的实参类型相对应 在初阶C语言的学习里面,我们了解到传参分为传址和传值两种类型 一起来复习一下吧👉【链接】 test函数里的是int类型,我们传过去的参数a也是int类型 12345678void test(int n){}int main(){ int a=1 test(a); return 0;} 好了,现在你已经知道了函数传参的基本概念了😁 那么就来分析一下数组传参、指针传参的代码吧! 1.一维数组传参 看看以下函数的代码示例 你觉得谁是正确的,谁是错误的呢? 12345678910111213141516171819include <stdio.h>void test(int arr[]){}void test(int arr[10]){}void test(int *arr){}void test2(int...
【C语言】指针进阶第三站,数组指针
[TOC] 上一站🚏我们学习了指针数组 今天来到我们的第三站🚌 寒假也不能落下学习! 今天学到了一个新的markdown语法 我是红色 1<font color=red>我是红色</font> 数组指针 整型指针:指向整型的指针 字符指针:指向字符的指针 数组指针:指向数组的指针 1基本概念 下面哪个是数组指针呢? 指针数组和数组指针的概念很容易混淆,一定要分清楚哦! 12int *p1[10];int (*p2)[10]; p1是指针数组,每个元素的类型是int* p2是数组指针,每个元素的类型是int(*)[10] 1234int (*p2)[10];//p2先和*结合,表示p2是一个指针变量//指向一个大小为10个整型的数组//所以p2是数组指针 注:[ ]的优先级高于*,所以必须加上()来保证p2先和*结合 1.1代码示例 12int* parr[6];int* (*pp)[6] =...
【C语言】指针进阶第二站,指针数组
[TOC] 嘟嘟嘟🚌,指针进阶的第二站指针数组到了! 上车上车! 回顾一下第一站🚍的内容:字符指针 指针数组 数组是一种类型的数的集合 整型数组的元素都是int类型 指针数组的元素都是指针变量 123int* arr1[10];//整型指针的数组char*arr2[10];//一级字符指针的数组char** arr3[5];//二级字符指针的数组 参考这一份示意图 示例1:定义多个字符指针 在上一站的字符指针里面,提到了可以直接用指针来创建一个常量字符串 同理,我们可以将多个指针放在一块,凑成指针数组,一次性创建多个指向常量字符串的指针 123456789101112int main(){ char* arr[] = { "abcdef", "qwer", "zhangsan" }; int i = 0; int sz = sizeof(arr) / sizeof(arr[0]); for (i = 0; i < sz; i++) ...
【C语言】指针进阶第一站,字符指针&typedef关键字
[TOC] 紧张刺激的寒假学习开始啦! 简单回顾一下指针的概念 内存会划分以字节为单位的空间,每一个字节都有一个编号(地址/指针) 指针变量可以存放这个地址/指针 注:我们日常所说的指针,一般是指针变量 下面让我们坐上指针进阶的🚌,来到第一站!字符指针 1字符指针 1.1代码示例1 12345678int main(){ char ch = 'w'; char* p= &ch; char* pa = "abcdef"; return 0;} 字符变量ch里面存放了字符w 字符指针p里面存放了ch的地址 指针变量pa里面存放了abcdef字符串的地址,我们并没有对这个字符串进行初始化。而是直接把它放进了指针变量pa里面。 和前两行的字符w不同,abcdef是存储在内存中的只读数据区,无法修改,即便通过指针也无法修改。 为了避免理解出错,我们一般会加上const修饰 1const char* pa =...