目录
- 前言
- atoi函数
- 宏offsetof
- 总结
前言
本章带大家一起认识一些在我们C语言标准库中的函数
atoi函数
int atio(const char* str);
头文件:
#include<stdlib.h>
参数:
str指向常量字符串起始位置的指针
函数介绍:
①解析C语言字符串str,将其内容解释为整数,返回一个int类型的值。
②函数丢弃空白字符,直到第一个非空白字符被找到,从该元素开始取一个可选的初始加号或减号,后面跟着以10基数的数字,并将它们解释为数值。(注意:初始加号或者减号后面跟着的必须是字符数字,只出现一次,其他情况下出现为非字符数字)
③如果字符串str中的第一个非空字符不是有效的整数,或者字符串str为空或字符串仅包含空白字符序列,则不执行转换,返回值为0。
④字符串中包含了非字符数字的字符,则非字符数字之前的字符数字(有效字符)直接被返回,后面的该非字符数字及其之后有效字符数字都不能被转换。
⑤如果函数转换成功,函数将转换之后的in类型的整数返回。如果转换后的值超过了int类型整数的取值范围,会导致未定义行为。
函数的使用案例:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i = atoi("");//字符串什么都没有
int a = atoi(" ");//字符串都为空字符
int b = atoi("a123");//第一个字符非数字字符
int c = atoi("000123#456");//字符串中间为非数字字符
int d = atoi("99999999999999999999999");
//有效字符的值超过int类型的取值范围
int e = atoi(" +-123456");//加减号同时出现
int m = atoi(" +123456");//只有减号出现
int n = atoi(" -123456");//只有加号出现
printf("%d\n", i);
printf("%d\n", a);
printf("%d\n", b);
printf("%d\n", c);
printf("%d\n", d);
printf("%d\n", e);
printf("%d\n", m);
printf("%d\n", n);
return 0;
}
代码运行的结果为:
atoi函数的模拟实现:
//需要考虑的情况
//空白字符
//+/-号
//溢出
//""空字符串
//空指针
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<ctype.h>
enum State
{
INVALID,
VALID
}state= INVALID;//默认表示非法
int my_atoi(const char* str)
{
assert(str);
if (*str == '\0')
{
return 0;
}
//isspace判断是否为空白字符
//是空白字符为真,否则为假
//跳过空白字符
while (isspace(*str))
{
str++;
}
int flag = 1;//判断初始正负号
if (*str == '+')
{
str++;
}
else if(*str=='-')
{
flag = -1;
str++;
}
long long ret = 0;//存放返回值
while (*str)
{
//isdigit判断是否为字符数字
if (isdigit(*str))
{
ret = ret * 10 + flag * (*str - '0');
if (ret > INT_MAX)
{
return INT_MAX;
}
else if (ret < INT_MIN)
{
return INT_MIN;
}
}
else
{
return (int)ret;
}
str++;
}
state = VALID;
return (int)ret;
}
int main()
{
int ret=my_atoi("123456");
if (state == VALID)
{
printf("%d\n", ret);
}
else
{
printf("非法字符串转换:%d\n",ret);
}
return 0;
}
代码运行的结果:
宏offsetof
宏使用形式:
offsetof(type, member)
头文件:
#include<stddef.h>
参数介绍:
type
为有效成员指示符的类型,一般为结构体或者联合体类型
member
为type类型的成员
宏的介绍:
该函数形式的宏返回的是结构体成员或联合体成员的偏移值(成员距离0偏移量的位置),单位为字节。
宏offsetof的使用例子:
#include<stddef.h>
#include<stdio.h>
struct S
{
char c1;
int i;
char c2;
};
int main()
{
printf("%d\n", offsetof(struct S,c1));
printf("%d\n", offsetof(struct S, i));
printf("%d\n", offsetof(struct S, c2));
return 0;
}
代码运行的结果:
宏offsetof的模拟实现:
//宏的模拟实现
#include<stdio.h>
struct S
{
char c1;//1/8 对齐数为1
int i;//4/8 对齐数为4
char c2;//1/8 对齐数为1
};
#define my_offsetof(type,member) (int)&(((type*)0)->member)
int main()
{
printf("%d\n",my_offsetof(struct S,c1));
printf("%d\n", my_offsetof(struct S, i));
printf("%d\n", my_offsetof(struct S, c2));
return 0;
}
代码运行的结果:
图形理解:
解释:
通过图形观察我们可以发现,结构体成员的起始地址和0偏移量地址相减的个数(地址之间的字节数)刚好就是该结构体成员的偏移量。既然这样,我们把0偏移量地址设为0,那么结构体成员变量的起始地址刚好也表示偏移量;我们在定义宏my_offsetof的时候,把整型变量0强转为结构体类型的指针变量,指向结构体里面的成员,然后取成员变量的地址随即强转为整型,得到便是该成员的偏移量。
总结
本章为大家介绍了函数atoi和宏offsetof的使用,希望对大家认识函数atoi和宏offsetof有些许帮助!最后感谢大家阅读,若有不对,欢迎指正!