为何C语言中memset函数的第二个参数类型为int而非char?
关于C语言memset函数的疑问
函数手册说明
memset()函数将指针s指向的内存区域的前n个字节填充为常量字节c。
memset的函数签名:
void *memset(void *s, int c, size_t n);
核心疑问
- 既然该函数是填充内存的前n个字节,为何参数c的类型是
int而非char?用char类型难道不能正常工作吗? - 若传入的c数值超过一个字节的大小会发生什么?
测试代码与输出
为验证问题编写的测试代码:
#include <string.h> #include <stdio.h> int main(int argc, char *argv[]) { char* s[5] = {0, 0, 0, 0, 0}; memset((void*)s, 257, 5); for (int i=0; i<5; i++) fprintf(stdout, " %d", s[i]); putc('\n', stdout); return 0; }
编译运行后的输出:
[amirreza@localhost memst]$ gcc memst.c [amirreza@localhost memst]$ ./a.out 16843009 0 0 0 0
问题解答
1. 参数c为何是int类型
这是C语言早期的历史设计遗留:在C的早期版本中,所有小于int的类型(如char、short)作为函数参数传递时,都会被自动提升为int类型。如果memset将c定义为char,调用时传入的char值依然会被转成int,所以直接把参数定义为int,既符合参数提升规则,也避免了额外的类型转换说明,同时保持了接口的一致性。
用char类型本身可以正常工作,但不符合C的参数传递习惯,且标准库接口已经沿用该定义至今。
2. 传入超过一个字节的c值的行为
根据C标准,memset会先将参数c转换为unsigned char,仅保留其**低8位(单字节)**的值,再用这个字节填充目标内存区域。比如传入的257(二进制100000001),最终会被处理为1(低8位00000001)。
3. 测试输出的解释
你定义的char* s[5]是一个指针数组,在32位系统中每个指针元素占4字节。调用memset(s, 257, 5)时,会把数组的前5个字节填充为1(257的低8位值):
- 第一个指针元素的4个字节被全部填充为
0x01,即0x01010101,转换成十进制就是16843009; - 第5个字节属于第二个指针元素,但仅填充了1个字节,剩下的3个字节仍为初始的0,所以第二个及以后的指针元素值还是0,这就对应了你看到的输出结果。
内容的提问来源于stack exchange,提问作者Amir reza Riahi
相关产品推荐
相关产品推荐

