下面一段程序中:
#include <stdio.h> #include <fcntl.h> #include <utmp.h> #include <unistd.h> #include <time.h> int main() { struct utmp ut; int fd = open(UTMP_FILE, O_RDONLY); int read_len = sizeof(ut); while (read_len == read(fd, &ut, sizeof(ut))) { if ( ut.ut_type != USER_PROCESS ) continue; printf("%-10.10s%-10.10s", ut.ut_user, ut.ut_line); time_t timeTmp = ut.ut_time; int32_t timeTmp1 = ut.ut_time; char *cp = ctime(&timeTmp); printf("%s\n", cp); } close(fd); }如果你将 char *cp = ctime(&timeTmp) 换做 char *cp = ctime(&timeTmp1),那么你将会得到错误的结果。
我们知道,time_t 是 long int,我64位机上是8Byte的长度,而 int32_t 是4Byte的长度,&相当于是把 timeTmp 的内存地址传递给 ctime(const time_t *) ,可是当换做 timeTmp1 后,相当于是把内存中暂存4Byte长度的 timeTmp1 的内存地址传递给 ctime() 函数,C函数对于指针的强制转换编译可以通过,可是当该函数中使用超出原有数据长度(4Byte)的时候,就危险了,因为其余数据是不确定的。所以C语言中当我们传参是指针时,最好确保类型是一样的,起码最好确保长度是一致的。
但是,如果是值传递,这种情况就不会存在,因为函数内定义的变量是局部变量,调用该函数时分配内存单元,存放在栈上,值传递相当于是复制,即使是不同类型,使用的当然是复制来的数据,断然不会出现溢出访问。即如果把该函数改为:
char *ctime(time_t tmp);
再调用 char *cp = ctime(timeTmp1) 断然不会出错。