0.0 C语言被我遗忘的知识点

文章目录

    • 位移运算(>>和<<)
    • 函数指针
      • 函数指针的应用场景
    • strcmp的返回值
    • 合法的c语言实数表示
    • sizeof 数组
    • 字符串的储存 —— 字符数组与字符指针
      • 字符串可能缺少 '\0' 的情况
    • 用二维数组储存字符串数组
      • 其他储存字符串数组的方法


位移运算(>>和<<)

右移(>>) 数值变为原数值÷2
右端移出的二进制数舍弃,左端(高位)移入的二进制数分两种情况:

  • 对于无符号整数和正整数,高位补0
  • 对于负整数,高位补1

左移(<<) 数值变为原数值×2
对于左移操作,不管是有符号数还是无符号数,行为通常是相同的

高位(左边)空出来的位总是用0来填充。
低位(右边)移出的数据一般会被丢弃。


函数指针

函数指针是在C语言中一种非常有用的特性,它允许你将函数当作参数传递给其他函数,或者在运行时决定调用哪个函数。函数指针可以让你的代码更加灵活和模块化。

函数指针的定义
函数指针是一种特殊类型的指针,它指向一个函数而不是一个变量。定义函数指针的基本语法如下:

return_type (*pointer_name)(parameter_types);
这里 return_type 是函数的返回类型,pointer_name 是函数指针的名字,parameter_types 是函数参数的类型列表。

示例
下面是一个简单的示例,演示了如何定义和使用函数指针:

#include <stdio.h>// 定义一个简单的加法函数
int add(int a, int b) {return a + b;
}// 定义一个简单的减法函数
int subtract(int a, int b) {return a - b;
}// 使用函数指针作为参数的函数
void performOperation(int (*operation)(int, int), int a, int b) {int result = operation(a, b);printf("Result: %d\n", result);
}int main() {// 定义一个函数指针int (*funcPtr)(int, int);// 将add函数的地址赋给函数指针funcPtr = add;performOperation(funcPtr, 5, 3);  // 调用 add(5, 3)// 将subtract函数的地址赋给函数指针funcPtr = subtract;performOperation(funcPtr, 5, 3);  // 调用 subtract(5, 3)return 0;
}

在这个示例中:

我们定义了两个函数 add 和 subtract,它们都接受两个整数参数并返回一个整数结果。
performOperation 函数接受一个函数指针 operation 作为参数,该函数指针指向一个接受两个整数并返回一个整数的函数。
在 main 函数中,我们定义了一个函数指针 funcPtr,并分别将其设置为指向 add 和 subtract 函数。
performOperation 函数根据传入的函数指针执行相应的操作。

输出
当运行上述程序时,输出将是:
Result: 8
Result: 2
这是因为 performOperation 函数根据传入的函数指针执行了加法和减法操作。

函数指针的应用场景

函数指针在许多场合都非常有用,例如:

  • 回调函数:在库函数中提供一个函数指针作为参数,以便库可以在适当的时候调用该函数。
  • 状态机:根据当前状态调用不同的函数。
  • 策略模式:在面向对象编程中,可以使用函数指针来实现某种形式的多态性。
  • 事件处理:在图形界面或其他交互式应用中,可以根据用户事件调用不同的处理函数

strcmp的返回值

strcmp(str1,str2)
如果两个字符串完全相同,strcmp 返回 0。

  • 如果str1在字典顺序上小于str2,strcmp 返回一个负数。
  • 如果str1在字典顺序上大于str2,strcmp 返回一个正数。


合法的c语言实数表示

B 是对的 .2e0
.2表示0.2
0表示指数
在这里插入图片描述
实型常量有小数形式和指数形式:

  • 小数形式:是由数字和小数点组成的一种实数表示形式; //123.456
  • 指数形式:类似于数学中的指数形式,C语言的语法规定,字母e或E之前必须要有数字,且e或E后面的指数必须为整数。故本题答案为B。//1.234e10

sizeof 数组

int main()
{char a[]={'a', 'b','c','d','e','f','g', 'h','\0'} ; int i,j;i=sizeof(a); j=strlen(a) ;printf("%d,%d\n",i,j);}
  • sizeof()函数是计算字符数组的长度,因为’\0’也是一个字符,要计算在内。在字符数组末尾加上’\0’作为字符串结束标志. 所以 i = 9
  • strlen()是计算字符串长度的函数,遇到’\0’即认为是字符串结束,不把空字符计入字符串的长度。j = 8

字符串的储存 —— 字符数组与字符指针

  • 字符数组
    char str2[] = "jason";
    类型: char str2[] 是一个字符数组。
    初始化: str2 被初始化为一个包含字符串 “jason” 的字符数组。
    存储: 字符数组 str2 在栈或静态存储区中分配空间,同样字符串的末尾会自动添加一个空字符 \0。
    可修改: 因为 str2 是一个数组,所以可以直接修改数组中的元素
  • 字符指针
    char* str1 = "jason";
    类型: char* 是一个指向 char 类型的指针。
    初始化: str1 被初始化为指向一个常量字符串 “jason”。
    存储: 常量字符串 “jason” 实际上是在程序的数据段中存储的,并且字符串的末尾会自动添加一个空字符 \0。
    不可修改: 因为 str1 指向的是一个常量字符串,所以不能通过 str1 修改这个字符串的内容。

字符串可能缺少 ‘\0’ 的情况

  • 手动赋值或复制:
    当你手动赋值或复制字符时不小心漏掉了 \0 时,可能会导致字符串缺少 \0。 例如,如果你使用循环逐个字符复制字符串但忘记添加 \0:
char src[] = "hello";
char dest[10];for (int i = 0; i < 5; i++) {  // 忘记添加 '\0'dest[i] = src[i];
}
上面的代码中,dest 数组将缺少 \0,因为它没有被显式添加。
  • 使用 memcpy:
    当使用 memcpy 复制字符串时,如果没有复制足够多的字符来包含 \0,也会导致字符串缺少 \0。
char src[] = "hello";
char dest[10];memcpy(dest, src, 5);  // 没有复制 '\0'
这里的 memcpy 只复制了前 5 个字符,没有复制 \0。
  • 从文件或其他来源读取字符串:
    如果从文件或其他数据源读取字符串,并且没有确保读取的字符串以 \0 结尾,也可能导致字符串缺少 \0。
char buffer[10];
FILE *file = fopen("data.txt", "r");
fread(buffer, 1, 9, file);  // 读取 9 个字符,没有 '\0'
fclose(file);
这里的 fread 只读取了 9 个字符,没有读取 \0。

用二维数组储存字符串数组

许久不用,才想起来竟然可以这样定义字符串数组
char a[5][10] = {"abcdef", "ghijkl", "mnopq", "rstuv", "wxyz"};

在 C 语言中,可以使用多维数组来存储多个字符串。在例子中,char a[5][10] 是一个二维字符数组,用来存储最多5个字符串,每个字符串最长9个字符(加上一个空字符 \0 作为字符串的终止符,使得每个子数组的大小为10)。

这种声明方式允许你在一个结构化的形式下管理多个字符串。每个 a[i] 都是一个指向数组 a[5][10] 中某个行首地址的指针,而这一行实际上就是一个字符串。

示例解释

深色版本
char a[5][10] = {"abcdef",   // 字符串 "abcdef" 将被复制到 a[0]"ghijkl",   // 字符串 "ghijkl" 将被复制到 a[1]"mnopq",    // 字符串 "mnopq" 将被复制到 a[2]"rstuv",    // 字符串 "rstuv" 将被复制到 a[3]"wxyz"      // 字符串 "wxyz" 将被复制到 a[4]
};

这里,a[0] 是一个指向 a[5][10] 中第一个元素的指针,即 “abcdef” 的起始地址。a[1] 指向 “ghijkl” 的起始地址,依此类推。

  • 如何理解
    char a[5][10] 定义了一个二维数组,其中包含5个元素,每个元素都是一个大小为10的字符数组。
    每个子数组(a[0], a[1], …, a[4])都可以用来存储一个字符串。
    初始化时,每个字符串会自动添加一个空字符 \0 作为结束标志。
  • 注意事项
    每个子数组必须有足够的空间来容纳它所存储的字符串以及终止符 \0。
    在这个例子中,每个子数组的大小是10,因此可以存储最多9个字符加上一个 \0。
    如果字符串长度超过9个字符,就会导致越界访问,从而可能引发未定义行为或程序崩溃。
  • 示例代码
    下面是一个简单的示例,演示如何使用这样的二维数组:
深色版本
#include <stdio.h>int main() {char a[5][10] = {"abcdef","ghijkl","mnopq","rstuv","wxyz"};for (int i = 0; i < 5; i++) {printf("%s\n", a[i]);  // 打印每个字符串}return 0;
}

这段代码会输出:

abcdef
ghijkl
mnopq
rstuv
wxyz

这种方法非常适合于需要同时处理多个固定长度字符串的场合。

其他储存字符串数组的方法

  • 使用指针数组
    你可以使用一个指针数组来存储指向各个字符串的指针。这种方式特别适合于字符串长度不确定的情况。
char *strings[] = {"abcdef","ghijkl","mnopq","rstuv","wxyz"
};

这种方式的好处是可以灵活地处理不同长度的字符串,缺点是需要额外的内存分配。

    1. 使用动态分配内存
      如果你不知道字符串的数量或者长度,可以使用动态内存分配来创建一个数组,然后逐个分配字符串的空间。

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#include <string.h>/*思路1.因为需要储存未知长度的字符串,所以我们选择 char指针指向字符串2.因为不知道要储存几个字符串,所以要用动态malloc给char指针分配空间,然后用char**类型的指针修改char*类型的指向。
*/
int main() {int num_strings = 5;char **strings = malloc(num_strings * sizeof(char *));if (strings == NULL) {printf("Memory allocation failed.\n");return 1;}
//strdup 是一个string库函数,它用于复制字符串并分配新的内存来存储该字符串的副本。
//它会返回一个指向新分配的内存区域的指针,该内存区域包含了原字符串的一个副本。strings[0] = strdup("abcdef"); //string是char类型指针的指针。  strings[1] = strdup("ghijkl"); //这里的string[0]其实是char类型的指针strings[2] = strdup("mnopq");strings[3] = strdup("rstuv");strings[4] = strdup("wxyz");for (int i = 0; i < num_strings; i++) {printf("%s\n", strings[i]);}// 释放内存for (int i = 0; i < num_strings; i++) {free(strings[i]);}free(strings);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/51560.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++中的匿名对象及内存管理

c中的匿名对象 A a;//a的生命周期在整个main函数中 a.Sum(1); //匿名对象生命周期只有一行&#xff0c;只有这一行会创建对象,出了这一行就会调析构 A().Sum(1);//只有这一行需要这个对象&#xff0c;其他地方不需要。 return 0; 日期到天数的转换 计算日期到天数转换_牛客…

【鸿蒙样式初探】多个组件如何共用同一样式

最近开发鸿蒙&#xff0c;刚接触难免二和尚摸不着头脑&#xff0c;尤其是样式...... 背景 在做银行卡显示的一个小需求时&#xff1a; 每个Text都需要设置fontColor:#FFFFFF" 想着是否可以简单点 解决历程 思路一&#xff1a;&#xff08;拒绝) 使用Styles 提取封装公…

爆改YOLOv8|利用可改变核卷积AKConv改进yolov8-轻量涨点

1&#xff0c;本文介绍 AKConv&#xff08;可改变核卷积&#xff09;是一种改进的卷积操作方法&#xff0c;其核心在于动态调整卷积核的形状和大小。与传统卷积层固定核大小不同&#xff0c;AKConv 通过引入可学习的机制&#xff0c;使卷积核在训练过程中能够自适应地调整&…

学生宿舍管理小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;宿舍公告管理&#xff0c;学生管理&#xff0c;宿舍管理&#xff0c;后勤人员管理&#xff0c;楼栋信息管理&#xff0c;宿舍分配管理管理&#xff0c;退宿信息管理 微信端账号功能包括&#xff1a;系…

程序猿成长之路之数据挖掘篇——Kmeans聚类算法

Kmeans 是一种可以将一个数据集按照距离&#xff08;相似度&#xff09;划分成不同类别的算法&#xff0c;它无需借助外部标记&#xff0c;因此也是一种无监督学习算法。 什么是聚类 用官方的话说聚类就是将物理或抽象对象的集合分成由类似的对象组成的多个类的过程。用自己的…

idea import配置

简介 本文记录idea中import相关配置&#xff1a;自动导入依赖、自动删除无用依赖、避免自动导入*包 自动导入依赖 在编辑代码时&#xff0c;当只有一个具有匹配名称的可导入声明时&#xff0c;会自动添加导入 File -> Settings -> Editor -> General -> Auto Imp…

简而不减,极致便捷!泰极预付费解决方案震撼上市

开户麻烦!绑表复杂!用电情况模糊!电费收缴难! 在日常生活中,能源缴费可能经常会遇到运维难管理、缴费收益难计算、支付安全难保障等问题。如何解决呢?正泰物联推出“泰极预付费解决方案”,“简”操作,“不减”功能,有效解决上述问题,助力实现便捷生活。 享轻松:泰极简而不减…

MySQL内部临时表(Using temporary)案例详解及优化解决方法

目录 前言 一.场景案例 二、什么是内部临时表&#xff1f; 三、哪些场景会使用内部临时表&#xff1f; 四、内部临时表如何存储&#xff1f; 1&#xff09;使用内存 2&#xff09;先使用内存&#xff0c;再转化成磁盘文件 3&#xff09;直接使用磁盘文件 五、如何优化…

【软件文档】项目总结报告编制模板(Word原件参考)

1. 项目概要 1.1. 项目基本信息 1.2. 项目期间 1.3. 项目成果 1.4. 开发工具和环境 2. 项目工作分析 2.1. 项目需求变更 2.2. 项目计划与进度实施 2.3. 项目总投入情况 2.4. 项目总收益情况 2.5. 项目质量情况 2.6. 风险管理实施情况 3. 经验与教训 3.1. 经验总结…

【异常错误】pycharm可以在terminal中运行,但是无法在run中运行(没有输出错误就停止了)

问题&#xff1a; pycharm的命令可以在terminal中运行&#xff0c;但是复制到无法在run中运行&#xff08;没有输出错误就停止了&#xff09; run中运行后什么错误提示都没有 搞不懂为什么 解决&#xff1a; 降低run中batch-size的大小&#xff0c;即可以运行 我并没有观察到…

Unity(2022.3.41LTS) - 后处理

目录 一、什么是后处理 二、后处理的工作原理 三、后处理的常见效果 四、如何在 Unity 中实现后处理 五、后处理的性能影响 六. 详细效果 一、什么是后处理 后处理是在场景渲染完成后&#xff0c;对最终图像进行的一系列操作。这些操作可以包括调整颜色、添加特效、模糊…

Windows Geth1.14.3私链搭建

geth下载官网&#xff1a;Downloads | go-ethereum 安装完成的目录 安装完后配置环境变量&#xff0c;在终端输入geth version 第一步&#xff1a;第一种创建账户方式geth account new --keystore keystore 创建一个账户&#xff0c;在当前目录下创建一个keystore的子目录&…

Linux工具使用

Linux编辑器-vim使用 1.vim的基本概念 在vim中&#xff0c;主要的三种模式分别是命令模式&#xff0c;插入模式和底行模式。 正常/普通/命令模式(Normal mode) 控制屏幕光标的移动&#xff0c;字符、字或行的删除&#xff0c;移动复制某区段及进入Insert mode下&#xff0c;…

一本读懂数据库发展史的书

数据库及其存储技术&#xff0c;一直以来都是基础软件的主力。数据库系统的操作接口标准&#xff0c;也是应用型软件的重要接口&#xff0c;关系重大。 作为最“有感”的系统软件&#xff0c;数据库的历史悠久、品类繁多、创新活跃。 对数据库历史发展的介绍&#xff0c;有利…

CSS3视图过渡动画

概述 网站的主题切换无非就是文字、背景图片或者颜色,我们可以先来看下 Element UI 官网的切换主题的动效: PS:Antdesign UI的主题切换动画也是大同小异。 实现的两种方式 CSS 为主 <script setup> const changeTheme = (e) => {if (document.startViewTransi…

深度学习实用方法 - 选择超参数篇

序言 在深度学习的浩瀚领域中&#xff0c;超参数的选择无疑是通往卓越模型性能的一把关键钥匙。超参数&#xff0c;作为训练前设定的、用于控制学习过程而非通过学习自动获得的参数&#xff0c;如学习率、批量大小、网络层数及节点数等&#xff0c;直接影响着模型的收敛速度、…

MySQL索引(三)

MySQL索引(三) 文章目录 MySQL索引(三)为什么建索引&#xff1f;怎么建立索引为什么不是说索引越多越好什么时候不用索引更好 索引怎么优化索引失效如何解决索引失效 学习网站&#xff1a;https://xiaolincoding.com/ 为什么建索引&#xff1f; 1.索引大大减少了MySQL需要扫描…

线性约束最小方差准则(LCMV)波束形成算法及MATLAB深入仿真分析

阵列信号处理——线性约束最小方差准则(LCMV)波束形成算法及MATLAB深入仿真分析 目录 前言 一、LCMV算法 二、仿真参数设置 三、抗干扰权值计算仿真 四、不同干扰方位下抗干扰性能仿真 五、不同信噪比和干噪比下抗干扰性能仿真 总结 前言 在信号处理模块中&#xff0c;通…

day13JS-MoseEvent事件

1. MouseEvent的类别 mousedown &#xff1a;按下键mouseup &#xff1a;释放键click &#xff1a;左键单击dblclick &#xff1a;左键双击contextmenu &#xff1a;右键菜单mousemove &#xff1a;鼠标移动mouseover : 鼠标经过 。 可以做事件委托&#xff0c;子元素可以冒泡…

【网络】网络层协议——IP协议

目录 1.TCP和IP的关系 2.IP协议报文 2.1. 4位首部长度&#xff0c;16位总长度&#xff0c;8位协议 2.2. 8位生存时间 &#xff0c;32位源IP地址和32位目的IP地址 3.IP地址的划分 3.1.IP地址的表现形式 3.2.旧版IP地址的划分 3.2.1.旧版IP地址的划分思路 3.2.2.分类划…