/* author s1n */
/* 不定期更新系列,都是在编程过程中发现的一些关于C的有趣的小问题 */
一,C语言中的time_t
1,看看time_t的定义
1 #ifndef __TIME_T 2 #define __TIME_T 3 typedef long time_t; /* 时间值time_t 为长整型的别名*/ 4 #endif
/* 在VS中的定义为__int64,即64位整型,与long long类似但并不等价,unsigned __int64可存储的最多位数。__int64与long long存储的位数相同 */
编写代码,在一个类型位time_t的变量中存放time_t的最大值,然后把它传递给ctime()函数,转换成ASCII字符串并打印出来:
/* 在64位linux下,sizeof(long)输出的结果为8 */
我写出,的程序如下,编译有note级别的提示:
note: expected ‘const time_t * {aka const long int *}’ but argument is of type ‘time_t {aka long int}’ extern char *ctime (const time_t *__timer) __THROW;
1 int main(){ 2 int n; 3 n=sizeof(long); 4 printf("longsize:%d\n",n); 5 time_t a = 0x7FFFFFF; 6 n=sizeof(time_t); 7 ctime(a); 8 printf("time_tsize:%d\n",n); 9 }
但无论a赋予何止,都不能正常运行。会产生段错误或总线错误。鉴于今天时间有限,所以先搁置此问题。
二,限制符与指针的赋值
尝试编译如下程序:
1 #include<stdio.h> 2 foo(const char **argv){} 3 int main(int argc, char **argv){ 4 foo(arvg); 5 }
得到错误提示:
warning: return type defaults to ‘int’ [-Wimplicit-int] foo(const char **argv){} ^~~ constchar.c: In function ‘main’: constchar.c:4:6: warning: passing argument 1 of ‘foo’ from incompatible pointer type [-Wincompatible-pointer-types] foo(argv); ^~~~ /* 注意此条错误 */ constchar.c:2:1: note: expected ‘const char **’ but argument is of type ‘char **’ foo(const char **argv){}
warning: passing argument 1 of ‘foo’ from incompatible pointer type
ANSI C标准中规定:
每个实参都应该具有自己的类型,这样他的值就可以赋值给与他多对应的形参类型的对象(该对象的类型不能含有限定符),因此参数传递的过程就类似于一个赋值的过程。
那么,如果类型为char **的值不可以赋值给类型位const char **的值,那么将产生一条报错语句。
进一步在ANSI C标准中寻找:
要使得上述的赋值形式合法,必须满足下列条件之一:
1).两个操作数都是指向有限定符或无限定符的相容类型的指针。
2).左边指针的所指向的类型必须具有右边指针所指向类型的全部限定符。
正是这个条件使得实参调用中char *可以和const char *匹配
因为在下面的代码中:
char*cp; const char * ccp; ccp = cp;
左操作数是一个指向有限定符的char指针,右操作数是一个指向没有限定符的char指针。
解释:char类型与char类型是相容的,左操作数所指向的类型具有右操作数所指类型的全部限定符(即无限定符),左边所指向的类型同时也具有右边指针所指向类型的全部限定符。因此,若此赋值语句倒过来(cp = ccp),则会产生编译错误。const char *所指向的并不是一个有限定符的指针,它所指向的是一个有限定符const的char类型的指针,而const *char 才是一个指向char的有const限定符的指针。类似地,const **也是一个没有限定符的指针,它指向的是一个有const限定符的char的指针的指针,由于char **和const char **都是没有限定符的指针,但其所指的类型不同,分别位char *和 const char*,因此,这二者是不相容的,他们违反了参数传递的约束条件,产生了编译错误的信息。