在Unix中通过引用值的类型转换来调用

时间:2013-12-25 21:43:42

标签: c unix casting porting

在我调试我的次要移植程序时,我对类型转换差异有疑问。

这是我的来源(下方):

  1 #include <time.h>
  2 #include <stdio.h>
  3 
  7 int main () {
  8     clock_t now; //unsigned long 
  9     struct tm * mac_time; // const long
 10     char *time_str;
 11     now = time (NULL);
 12     mac_time = localtime((const long *)&now); 
 13                           // localtime ( const long <- unsigned long)
 13     time_str = asctime(mac_time);
 14     printf("Now : %s\n",time_str);
 15     return 0;
 16 }

首先,它正常工作,现在没有错误。但我对类型铸造差异有疑问。

在第12行中,由于发生了类型转换警告,我更改了值的类型以进行调试。

之间有什么区别
12     mac_time = localtime((const long *)&now);

12     mac_time = localtime(&(const long *)now);

我认为彼此之间没有区别,因为这只与'铸造价值的地址和'价值的地址铸造'不同。

但是编译器抛出后一个警告信息。

你会就这种类型的铸造问题给我一些建议吗?

3 个答案:

答案 0 :(得分:5)

(const long *)&now获取now的地址,并将其解释为const long的地址。

&(const long *)nownow解释为const long的地址,并获取该地址的地址。这很危险,因为您基本上将整数或浮点数转换为指针,而没有任何理由说明为什么now标识的内存位置可供您的应用程序访问。

答案 1 :(得分:4)

案例

mac_time = localtime((const long *)&now);  

您将&now类型的pointer to clock_t投射到const long *,即指向const long类型的指针。如果localtime期望pointer to const long类型的参数,则没问题。而在第二种情况下

 mac_time = localtime(&(const long *)now);  

now属于clock_t,您将其投射到const long *,然后尝试将其地址传递给函数,编译器显示错误。
现在关于错误:

error: cannot take the address of an rvalue of type 'const long *' mac_time = localtime(&(const long *)now); 

你应该注意到,施法产生r-value。另一方面,&需要l值作为操作数。这就是为什么你不能做&(const long *)now而编译器抛出错误的原因。

最后请注意 C中没有引用来电,而是所有来电都是

答案 2 :(得分:4)

指针强制转换完全没必要。如果你的程序看起来有效,那就太巧合了。 (我说“不走运”,因为这意味着错误未被诊断出来。)

localtime()的参数类型为const time_t*不是 clock_t*time_tclock_t是不同的类型,用于不同的目的,即使它们可能碰巧在某些特定实现中以相同的方式定义。

now的定义更改为:

time_t now;

并按照以下方式致电localtime

mac_time = localtime(&now);

任何演员,特别是指针演员,都应该怀疑。当真正的解决方案是修复代码以便首先使用正确的类型声明事件时,强制转换通常用于使编译器警告静音。

至于你问的问题 - 嗯,这并不重要,因为代码根本不正确。这样:

mac_time = localtime((const long *)&now)

获取now的地址(在您的代码中,类型为clock_t*),并将其转换为const long*。由于localtime期望类型为const time_t*的参数,并且显然 time_t在您的实现中定义为long,因此出现

此:

mac_time = localtime(&(const long *)now);

获取now(此时尚未初始化)并将其转换为const long*;换句话说,它采用垃圾数值并将其转换为指针。然后它尝试获取该指针的地址 - 但由于它是指针,而不是指针对象,因此它没有地址。以上是编译时错误。 (我希望您的编译器将此视为致命错误,而不仅仅是警告。)

但是忘了这一切。只需首先声明您的对象是正确的类型,您就不必担心强制转换。

(有些情况下,演员阵容,甚至指针演员阵容都是必要且恰当的,但不适合你在这里尝试做的事情。)