<stdlib.h>头文件: C 语言常用标准库函数详解

2023-12-24 06:52

本文主要是介绍<stdlib.h>头文件: C 语言常用标准库函数详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 引言
    • 1. `<stdlib.h>` 概览
      • 1.1 头文件包含
    • 2. 内存管理函数
      • 2.1 `malloc` 函数
      • 2.2 `calloc` 函数
      • 2.3 `realloc` 函数
      • 2.4 `free` 函数
    • 3. 随机数生成函数
      • 3.1 `rand` 函数
      • 3.2 `srand` 函数
    • 4. 字符串转换函数
      • 4.1 `atoi` 函数
      • 4.2 `atof` 函数
      • 4.3 `itoa` 函数
      • 4.4 `ltoa` 函数
      • 4.5 `ultoa`函数
    • 5 其他函数
      • 5.1 `qsort`函数
        • compare 的示例
      • 5.1 `swab`函数
      • 5.12`bsearch`函数
    • 结语

引言

在C语言中,<stdlib.h> 是一个重要的头文件,它包含了一些标准库函数,提供了内存分配、随机数生成、字符串转换等功能。本博客将深入解析 <stdlib.h> 头文件,介绍其中一些常用函数的用法和实现原理。


1. <stdlib.h> 概览

<stdlib.h> 是 C 标准库的一部分,它定义了一些宽泛的实用函数。这些函数通常涉及内存管理、伪随机数生成、整数转换等方面。

1.1 头文件包含

在使用 <stdlib.h> 头文件之前,我们通常会在程序中包含以下语句:

#include <stdlib.h>

这样可以确保我们在程序中使用标准库函数时能够正确调用相应的功能。


2. 内存管理函数

2.1 malloc 函数

  • 功能:malloc 函数用于在堆上分配一块指定大小的内存空间。成功时返回指向分配内存的指针,失败时返回 NULL
  • 原型:void* malloc(size_t size);
#include <stdio.h>
#include <stdlib.h>int main() {// 定义一个指针,分配包含 5 个整数的内存块int *dynamicArray = (int *)malloc(5 * sizeof(int));// 检查内存是否成功分配if (dynamicArray == NULL) {printf( "内存分配失败\n");return 1; // 返回错误代码}// 向动态数组中写入数据int i;for (i = 0; i < 5; ++i) {dynamicArray[i] = i * 2;}// 输出动态数组的内容printf("动态数组的内容:\n");for (i = 0; i < 5; ++i) {printf("%d ", dynamicArray[i]);}// 释放动态分配的内存free(dynamicArray);return 0;
}
动态数组的内容:
0 2 4 6 8

2.2 calloc 函数

  • 功能:calloc 函数用于在堆上分配一块指定数量和大小的内存空间,与 malloc 不同的是,calloc 会将分配的内存块初始化为零。
  • 原型: void* calloc(size_t num, size_t size);

例如 int* 初始化就是0
char* 初始化就是’\0’

#include <stdio.h>
#include <stdlib.h>int main() {// 定义一个指针,用于存储分配的内存地址int *dynamicArray;// 使用 calloc 分配包含 5 个整数的内存块dynamicArray = (int *)calloc(5, sizeof(int));// 检查内存是否成功分配if (dynamicArray == NULL) {fprintf(stderr, "内存分配失败\n");return 1; // 返回错误代码}// 输出动态数组的内容,此时数组已被初始化为零printf("动态数组的内容:\n");int i;for (i = 0; i < 5; ++i) {printf("%d ", dynamicArray[i]);}// 释放动态分配的内存free(dynamicArray);return 0;
}
动态数组的内容:
0 0 0 0 0

2.3 realloc 函数

  • 功能:realloc 函数用于修改之前由 malloccallocrealloc 分配的内存块的大小。它可以用于扩大或缩小内存块。
  • 原型: void* realloc(void* ptr, size_t size);
#include <stdio.h>
#include <stdlib.h>int main() {// 初始分配 10 个整数大小的内存块int *arr = (int *)malloc(10 * sizeof(int));if (arr == NULL) {fprintf(stderr, "内存分配失败\n");return 1;}printf("初始分配内存后的地址:%p\n", (void *)arr);// 使用 realloc 缩小内存块到 5 个整数大小int *newArr = (int *)realloc(arr, 5 * sizeof(int));if (newArr == NULL) {fprintf(stderr, "内存重新分配失败\n");free(arr);  // 如果 realloc 失败,需要释放原始的内存块return 1;}printf("缩小内存后的地址:%p\n", (void *)newArr);// 现在 newArr 可以用于存储 5 个整数// 不要忘记释放内存free(newArr);return 0;
}

2.4 free 函数

  • 功能:free 函数用于释放之前由 malloccallocrealloc 分配的内存空间。释放后,该指针不再指向有效的内存区域。
  • 原型:void free(void* ptr);
// 例子
free(arr);

3. 随机数生成函数

3.1 rand 函数

  • 功能:rand 函数用于生成一个伪随机数。每次调用 rand 都会返回一个范围在 0 到 RAND_MAX 之间的整数。
  • 原型:int rand(void);

请注意,rand 函数生成的是伪随机数,其实际上是通过一定的算法计算的,因此不是真正的随机数。

#include <stdio.h>
#include <stdlib.h>int main() {int randomNum1 = rand();int randomNum2 = rand();// 打印随机数printf("Random Number 1: %d\n", randomNum1);printf("Random Number 2: %d\n", randomNum2);return 0;
}
// 第一次运行
Random Number 1: 41
Random Number 2: 18467// 第二次运行
Random Number 1: 41
Random Number 2: 18467
...

3.2 srand 函数

  • 功能:srand 函数用于设置 rand 函数的种子值,以便生成不同的随机数序列。
  • 原型: void srand(unsigned int seed);
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {// 没有使用 srand 设置种子printf("未使用 srand:\n");int i;for (i = 0; i < 5; ++i) {printf("%d ", rand());}// 使用 srand 设置种子srand(time(NULL)); // 42 只是一个示例种子值,可以是任何值printf("\n使用 srand:\n");for (i = 0; i < 5; ++i) {printf("%d ", rand());}return 0;
}
// 第一次运行
未使用 srand:
41 18467 6334 26500 19169
使用 srand:
29346 6213 16299 17151 17694// 第二次运行
未使用 srand:
41 18467 6334 26500 19169
使用 srand:
29372 26664 28140 13050 1907...

在这个例子中,srand(time(NULL)) 使用当前时间作为随机数生成器的种子。由于时间每次都在变化,这样就能确保每次运行程序都会得到不同的随机数序列。


4. 字符串转换函数

4.1 atoi 函数

  • 功能:atoi 函数用于将字符串转换为整数。
  • 原型: int atoi(const char* str);
#include <stdio.h>
#include <stdlib.h>int main() {// 定义一个字符串char str1[] = "12345";char str2[] = "12345abdc";// 使用atoi将字符串转换为整数int num1 = atoi(str1);int num2 = atoi(str2);// 打印结果printf("String str1: %s\n", str1);printf("Integer int1: %d\n", num1);printf("String str2: %s\n", str2);printf("Integer int2: %d\n", num2);return 0;
}
String str1: 12345
Integer int1: 12345
String str2: 12345abdc
Integer int2: 12345

4.2 atof 函数

  • 功能:atof 函数用于将字符串转换为浮点数。
  • 原型: double atof(const char* str);
#include <stdio.h>
#include <stdlib.h>int main() {// 定义字符串char str1[] = "12345.137";char str2[] = "12345.111abdc";// 使用atof将字符串转换为浮点数double num1 = atof(str1);double num2 = atof(str2);// 打印结果printf("字符串 str1:%s\n", str1);printf("浮点数 num1:%lf\n", num1);printf("字符串 str2:%s\n", str2);printf("浮点数 num2:%lf\n", num2);return 0;
}
字符串 str1:12345.137
浮点数 num1:12345.137000
字符串 str2:12345.111abdc
浮点数 num2:12345.111000

4.3 itoa 函数

  • 功能:itoa 函数用于将整数转换为字符串。它接受三个参数:要转换的整数 value,存储结果的字符串指针 str,和进制 basebase 可以是 2 到 36 之间的任意值,表示输出的字符串使用的进制。
  • 原型: char* itoa(int value, char* str, int base);
#include <stdio.h>
#include <stdlib.h>int main() {// 定义整数int num1 = 12345;int num2 = -6789;// 定义足够大的字符数组来存储转换后的字符串char str1[20];char str2[20];// 使用 itoa 将整数转换为字符串itoa(num1, str1, 10);  // 第三个参数是基数,这里使用10进制itoa(num2, str2, 10);// 打印结果printf("整数 num1:%d\n", num1);printf("字符串 str1:%s\n", str1);printf("整数 num2:%d\n", num2);printf("字符串 str2:%s\n", str2);return 0;
}
整数 num1:12345
字符串 str1:12345
整数 num2:-6789
字符串 str2:-6789

4.4 ltoa 函数

  • 功能:将长整型转换为字符串,参数和用法与 itoa 类似-
  • 原型: char* ltoa(long value, char* str, int base);
#include <stdio.h>
#include <stdlib.h>int main() {// 定义整数long num1 = 12345;long num2 = 987654321;// 使用ltoa将整数转换为字符串char str1[20];  // 假设足够大以容纳转换后的字符串char str2[20];  ltoa(num1, str1, 10);ltoa(num2, str2, 10);// 打印结果printf("整数 num1:%ld\n", num1);printf("字符串 str1:%s\n", str1);printf("整数 num2:%ld\n", num2);printf("字符串 str2:%s\n", str2);return 0;
}
整数 num1:12345
字符串 str1:12345
整数 num2:987654321
字符串 str2:987654321

4.5 ultoa函数

  • 功能:将无符号长整型转换为字符串,参数和用法与 itoa 类似
  • 原型: char* ultoa(unsigned long value, char* str, int base);
#include <stdio.h>
#include <stdlib.h>int main() {// 定义无符号长整型数unsigned long num1 = 12345;unsigned long num2 = 879631;// 定义存储转换后字符串的数组char str1[20]; // 大小需要足够存储转换后的字符串char str2[20];// 使用 ultoa 将无符号长整型数转换为字符串ultoa(num1, str1, 10);ultoa(num2, str2, 10);// 打印结果printf("无符号长整型数 num1: %lu\n", num1);printf("字符串 str1: %s\n", str1);printf("无符号长整型数 num2: %lu\n", num2);printf("字符串 str2: %s\n", str2);return 0;
}
String str1: 12345
Integer int1: 12345
String str2: 879631
Integer int2: 879631

5 其他函数

5.1 qsort函数

qsort & bsearch 实现二分查找

  • 功能:用于对数组进行快速排序的函数
  • 原型: void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));

下面对函数的参数进行详解:

  • base:指向要排序的数组的起始地址的指针。
  • nmemb:数组中元素的个数。
  • size:数组中每个元素的大小(以字节为单位)。
  • compar:比较函数的指针。这个函数用于定义数组元素之间的比较规则。它接受两个指向元素的指针,比较这两个元素的大小,并返回一个整数,表示它们的相对顺序。比较函数的返回值有三种情况:
    • 若返回值小于 0,则表示第一个元素要在第二个元素后面
    • 若返回值等于 0,不进行操作
    • 若返回值大于 0,则表示第一个元素要在第二个元素之前

qsort 函数使用快速排序算法,这是一种高效的排序算法,平均时间复杂度为 O(n log n)。排序是在原地进行的,不需要额外的辅助数组。

以下是一个简单的示例,演示如何使用 qsort 函数:

#include <stdio.h>
#include <stdlib.h>// 比较函数
int compare(const void *a, const void *b) {return (*(int *)a - *(int *)b);
}int main() {int arr[] = {5, 2, 9, 1, 5, 6};size_t n = sizeof(arr) / sizeof(arr[0]);// 调用 qsort 函数进行排序qsort(arr, n, sizeof(arr[0]), compare);// 输出排序后的数组for (size_t i = 0; i < n; i++) {printf("%d ", arr[i]);}return 0;
}
1 2 5 5 6 9

在这个例子中,compare 函数用于比较整数,将数组元素按升序排序。qsort 函数将会根据 compare
函数的定义对数组进行排序。在实际使用中,可以根据需要定义不同的比较函数来实现不同的排序规则。

compare 的示例

整型

int cmp_int(const void* e1, const void* e2)
{return *(int*)e1 - *(int*)e2;
}

浮点型

int cmp_float(const void* e1, const void* e2)
{return (int)(*(float*)e1 - *(float*)e2);
}

字符串

int cmp_str_size(const void* e1, const void* e2)
{return strcmp((char*)e1,(char*)e2);
}

字符串的长度

int cmp_str_len(const void* e1, const void* e2)
{return strlen((char*)e1)-strlen((char*)e2);
}

结构体

int cmp_by_age(const void*e1, const void*e2)
{return (int)(((stu*)e1)->weight - ((stu*)e2)->weight);
}

需要注意的是:返回结果一定要确保是整形,如果不是一定要强制类型转换成整形!

5.1 swab函数

  • 功能:在不同字节序之间交换数据
  • 原型: void swab(char *from,char *to,int n);
#include<stdio.h>
#include<stdlib.h>
#include<string.h>int main(void){char suc[20]={"1234567890"};char des[20];swab(suc,des,strlen(suc));printf("This is  suc: %s\n",suc);printf("This is dest: %s\n",des);return 0;}
This is  suc: 1234567890
This is dest: 2143658709

5.12bsearch函数

qsort & bsearch 实现二分查找

  • 功能:用于二分法搜索
  • 原型: void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));

参数说明:

  • key:要查找的元素的指针,即要在数组中查找的元素。
  • base:指向已排序数组的起始地址的指针。
  • nmemb:数组中元素的个数。
  • size:每个元素的大小(以字节为单位)。
  • compar:比较函数的指针,用于定义元素之间的比较规则。该函数应返回一个整数,表示两个元素的相对顺序。

bsearch函数的返回值是一个指向匹配元素的指针,如果找到匹配的元素,则返回指向该元素的指针;如果没有找到匹配的元素,则返回NULL

比较函数compar的原型如下:

int compar(const void *a, const void *b);

比较函数应该返回一个整数,其含义如下:

  • 如果a小于b,则返回负值。
  • 如果a等于b,则返回零。
  • 如果a大于b,则返回正值。
#include <stdio.h>
#include <stdlib.h>// 比较函数,用于定义整数之间的比较规则
int compareIntegers(const void *a, const void *b) {return (*(int*)a - *(int*)b);
}int main() {int arr[] = {1, 2, 4, 6, 8, 10, 12, 14, 16, 18};int size = sizeof(arr) / sizeof(arr[0]);int key = 12;// 使用bsearch在已排序数组中查找元素int *result = (int*)bsearch(&key, arr, size, sizeof(arr[0]), compareIntegers);if (result != NULL) {printf("元素 %d 找到在数组中的位置:%ld\n", key, result - arr);} else {printf("元素 %d 未找到\n", key);}return 0;
}
元素 12 找到在数组中的位置:6

结语

<stdlib.h> 头文件提供了许多在 C 语言中常用的功能,从内存管理到随机数生成,再到字符串转换,都有涉及。熟练掌握这些函数的用法,有助于提高程序的效率和可维护性。

请记得在使用这些函数时要注意内存的分配和释放,以免造成内存泄漏和其他不稳定的行为。希望本博客对你理解和使用 <stdlib.h> 有所帮助。如有疑问或建议,欢迎留言讨论。

这篇关于<stdlib.h>头文件: C 语言常用标准库函数详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/530913

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

常用的jdk下载地址

jdk下载地址 安装方式可以看之前的博客: mac安装jdk oracle 版本:https://www.oracle.com/java/technologies/downloads/ Eclipse Temurin版本:https://adoptium.net/zh-CN/temurin/releases/ 阿里版本: github:https://github.com/

30常用 Maven 命令

Maven 是一个强大的项目管理和构建工具,它广泛用于 Java 项目的依赖管理、构建流程和插件集成。Maven 的命令行工具提供了大量的命令来帮助开发人员管理项目的生命周期、依赖和插件。以下是 常用 Maven 命令的使用场景及其详细解释。 1. mvn clean 使用场景:清理项目的生成目录,通常用于删除项目中自动生成的文件(如 target/ 目录)。共性规律:清理操作

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)