首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

C编程小疑点

2013-01-28 
C编程小问题看了些小代码,写C的时间不算长。有个疑问就是为什么见过好几次,C的库函数的输入参数要求是指针

C编程小问题
看了些小代码,写C的时间不算长。有个疑问就是为什么见过好几次,C的库函数的输入参数要求是指针呢?比如:


#include <stdio.h>
#include <time.h> 
#include <limits.h>
main(){
long int t;
char* s=NULL;
t=INT_MAX;
s=ctime(&t);
printf("%s\n",s);


关于这个小代码有两个疑问:
(1)为什么传给ctime函数的参数需要是指针呢?它声明为:

char *ctime(const time_t *timer);

为什么不是

char *ctime(time_t timer);

(2)函数为什么开辟了额外的空间呢?为什么不是:

char *ctime(char buffer[],const time_t *timer);

或者

char *ctime(char buffer[],const time_t *timer, size_t size);

这样的目的是传入一个已经开辟空间的buffer用于填充返回的时间字符串信息。函数库中的方式容易导致内存泄露吧?觉得比较矛盾,命名是传值调用,传一个const的int指针和传递一个int值的代价应该是同等的;像string.h中的strcat, strcpy, memcopy等等这些都是需要事先申请buffer的。我也不是否定库的实现方式,只是想问问大家的看法,库的实现是不是不够好? c
[解决办法]
这个问题主要关系到C函数的参数传递问题。
严格地讲,C总是按值传递。你可以直接模拟按引用传递,定义接受指针的函数,然后在调用时使用&操作符。
如果你经常使用C的qsort,你对C的参数传递将会有更深的理解。
C没用“按引用传递”,真的没用。
声明为:
char *ctime(const time_t *timer);
我理解的原因是:const修饰符的作用,函数它本身不希望更改你传递给它的参数。大部分的C库函数都使用这种声明方式。所以如果你决定用C编程的话,这一点要记牢。

函数并没有开辟额外的空间。我的理解是这样的:
当你声明为char *ctime(time_t timer);时,将参数传递给ctime时,实际上在ctime函数里面,timer已经是参数的一个副本,也就是说,无论你在ctime函数里面对timer做了如何的修改,函数结束后,参数的值并没有改变。
而函数声明为char *ctime(time_t *timer);时,将参数传递给ctime时,实际上只是用另外一个名字timer代替了参数的名字,他们都是指向同一块内存。就像是一个房间配了两把钥匙。
再就是C真的没有“按引用传递”。
[解决办法]
这问题,多看库函数手册。


ctime:
<ctime>
char * ctime ( const time_t * timer );
Convert time_t value to string
Converts the time_t object pointed by timer to a C string containing a human-readable version of the corresponding local time and date.

The returned string has the following format:

Www Mmm dd hh:mm:ss yyyy 
Where Www is the weekday, Mmm the month in letters, dd the day of the month, hh:mm:ss the time, and yyyy the year.

The string is followed by a new-line character ('\n') and the terminating null-character.

This function is equivalent to: asctime(localtime(timer)).

Parameters:
timer
Pointer to a time_t object that contains a calendar time.

Return Value:
A C string containing the date and time information in a human-readable format.

The array which holds this string is statically allocated and shared by both the ctime and asctime functions. Each time either one of these functions is called the content of this array is overwritten.

Example
/* ctime example */
#include <stdio.h>
#include <time.h>

int main ()
{
  time_t rawtime;

  time ( &rawtime );


  printf ( "The current local time is: %s", ctime (&rawtime) );
  
  return 0;
}


[解决办法]
引用:
还想问一下,那块空间已经是静态分配的,为什么10L的程序能够正常运行呢?

楼主啊 !我来回答你吧!
The array which holds this string is statically allocated and shared by both the ctime and asctime functions. Each time either one of these functions is called the content of this array is overwritten.
意思是说这个数组所占的内存区域是在静态区域分配的,在程序运行时一直存在。而且块区域是ctime和asctime函数所共享的,每次调用这两个函数都是访问的这同一块区域。就算你第二次、第n次调用也不会开辟新的内存,因为这块内存早就准备好了。只等你调用就把这块内存地址返回给你。所以不会造成内存泄露。

至于线程安全,这里的情况是如果多个线程访问这同一快区域。有可能一个线程正在改变这块内存区域的值,只改了一半,这时其他线程访问到的这个内存区域的值是不正确的(毕竟人家正在修改它)。当然还有其他情况。学操作系统时讲线程时都讲过的。拿书出来翻翻吧。
[解决办法]
给函数传参传指针而不是非指针比较有效率,尤其是对于比较大的类型比如long long或者struct什么的时候。

第二个问题看ctime的man page:
NOTES
       The  four functions asctime(), ctime(), gmtime() and localtime() return
       a pointer to static data and hence are  not  thread-safe.   Thread-safe
       versions asctime_r(), ctime_r(), gmtime_r() and localtime_r() are spec-
       ified by SUSv2, and available since libc 5.2.5.

热点排行