前言
😽这里介绍atoi、offsetof以及它们的模拟实现,atoi这个库函数用来将一个字符串转化为一个数字;offsetof用来计算偏移量,长的像个函数,其实它是一个宏!
一. atoi库函数
1. 介绍
功能:
- 将一个数字字符串转化为其对应的整数
int atoi (const char * str);
头文件:
<stdlib.h>
参数:
str——指向要进行转化的字符串的指针
返回值:
成功时,函数将转换后的整数作为int值返回;
如果不能进行转换,返回0;
如果转换后的值超出int的可表示值范围,则行为未定义。
注意事项:
atoi在使用时,如果要转化的字符串前面有空白字符,则会跳过这些空白字符,直到找到第一个非空白字符;
要被转化的字符串中开头可以带 + - 号这样的字符,会被识别为算数当中的 + - 号;
如果要转化的数字字符之间有非非数字字符,则非数字字符之后的数字字符无法被转化。
使用实例:
2. 模拟实现
atoi的模拟要尽可能模拟全面,要考虑到如下几点:
- 参数为空指针
- 参数为空字符串
- 字符串最开头空格
- 第一个数字字符前的 + - 号
- 转化后的值越界,超出int的范围
- 字符串中的非数字字符
#include<stdio.h> #include<assert.h> #include<limits.h> #include<ctype.h> enum Status { VALID, INVALID }sta = INVALID;//默认非法 int My_atoi(const char* str) { int flag = 1; assert(str); if (*str == '\0') { return 0;//返回的非法0 } //跳过空白字符 while (isspace(*str)) { str++; } //解决+-号 if (*str == '+') { flag = 1; str++; } else if (*str == '-') { flag = -1; str++; } long long ret = 0; while (*str) { if (isdigit(*str)) { ret = ret * 10 + flag * (*str - '0'); //判断越界 if (ret > INT_MAX || ret < INT_MIN) { return 0; } } else { return (int)ret; } str++; } if (*str == '\0') { sta = VALID; } return (int)ret; } int main() { char arr[50] = "-1234"; int ret = My_atoi(arr); if (sta == INVALID) { printf("非法返回:%d\n", ret); } else if(sta == VALID) { printf("合法转换:%d\n", ret); } return 0; }
二. 宏offsetof
1. 介绍
功能:
- 计算结构成员相对于结构体首地址的偏移量
offsetof (type,member)
参数:
- type——结构或者联合类型
- member——类型中的成员
返回值:
- 返回成员相对于类型首地址的偏移量,一个size_t类型的值。
使用实例:
2. 模拟实现
去观察结构体的地址和结构成员的地址会发现,结构体成员的地址减去结构体的地址就是结构体成员相对于结构体首地址的偏移量;
假设0地址处为结构体的地址,那么结构体成员的地址就是其的相对于结构体首地址的偏移量
#include<stdio.h> #define OFFSETOF(type, name) (int)&(((struct S*)0)->name) struct S { int a; char b; double c; }; int main() { printf("%d\n", OFFSETOF(struct S, a)); printf("%d\n", OFFSETOF(struct S, b)); printf("%d\n", OFFSETOF(struct S, c)); return 0; }