首先声明一下,在我们写的程序中,会使用到一个头文件# include <head.h>
因为,在linux系统编程的时候,会用到很多头文件,为此,我用一个头文件全部包含在一起,头文件内容如下:
# ifndef _OK_
# define _OK_
# include <stdio.h>
# include <string.h>
# include <errno.h>
# include <stdlib.h>
# include <time.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <sys/types.h>
# include <dirent.h>
# include <pwd.h>
# include <grp.h>
# include <pthread.h>
# include <semaphore.h>
# include <signal.h>
# include <linux/ipc.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <sys/wait.h>
# include <netdb.h>
#define LOG(...){char _bf[1024];snprintf(_bf,sizeof(_bf),__VA_ARGS__);\
fprintf(stderr,"%s",_bf);syslog(LOG_ERR,"%s",_bf);}
#endif
编辑好了之后,放到/usr/include/下即可。
1.使用__FILE__,__FUCTION__,__LINE__等宏能自动定位到程序执行到哪一个函数的哪一行,作为一个经典的调试方法,很容易被人忽略,也很重要。如下:
#include <stdio.h>
void test()
{
printf("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
}
void test_1()
{
printf("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
test();
}
int main()
{
printf("1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 =%d\n",1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10);
printf("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
test_1();
return 0;
}
打印:
2.对于malloc动态内存分配,现在只是给出一个实例,让大家有一个感性的认识,要知道malloc主要用来动态开辟内存空间的,一般malloc都是和free配对的。以后会专门讲解的。下面的一个实例是动态开辟一个一维数组,比较简单。
# include <stdio.h>
# include <stdlib.h>
void input(int *array,int len)
{
int i;
printf("input %d numbers",len);
for(i=0; i<len; i++)
{
setbuf(stdin,NULL);
scanf("%d",array+i);
}
}
int main()
{
int n=0,i=0;
int *a,array[n];
printf("input characters ");
scanf("%d",&n);
a = (int*)malloc(n*sizeof(int));
input(a,n);
printf("the characters you input are ");
for(i=0;i<n; i++)
printf("%d ",a[i]);
printf("\n");
printf("a = %p,array = %p\n",a,array);
free(a);
a = NULL;
return 0;
}
程序要注意几点:
在C99标准中,准许使用下面的做法,但是不推荐
int n = 0;
scanf(“%d”,&n);
int ch[n] ;
在两次连着输入的时候,注意清除键盘缓存,在linux下可以用setbuf(),在Windows下可以用fflush()等,关于清除缓存,以后会专门讲解。
再次强调,malloc一定要和free配对使用,如果申请的空间不释放,一次两次也许不会有什么错误,申请多了就会发生内存泄漏,系统崩溃等严重问题,所以不要抱有侥幸心理。释放之后,a就是一个野指针了,一般而言,要将其赋为空,这是一个很好的习惯,希望大家坚持。
3.大家看看下面的程序的输出结果是什么?
# include <stdio.h>
int main()
{
inta[5]={0x10111213,0x20212223,0x30313233,0x40414243,0x50515253};
printf("a[5]={0x10111213,0x20212223,0x30313233,0x40414243,0x50515253}");
printf("\na = %p\n&a = %p\n",a,&a);
printf("a+1 = %p\n&a+1 = %p\n",a+1,&a+1);
printf("&a[0] = %p\n&a[0]+1 =%p\n",&a[0],&a[0]+1);
printf("\nsizeof(a) = %d\nsizeof(&a) =%d\n",sizeof(a),sizeof(&a));
printf("sizeof(&a[0]) = %d\n
sizeof(&a[5]) =%d\n",sizeof(&a[0]),sizeof(&a[5]));
printf("sizeof(&a[10]) = %d\n
sizeof(a[5]) =%d\n\n",sizeof(&a[10]),sizeof(a[5]));
return 0;
}
输入结果:
为什么会这样呢?大家都知道a是一个数组名,准确的讲,a是该数组首元素的地址,而&a是什么呢?&a是整个数组的地址。就像一栋房子一楼的门卫室,如果门卫室坐落在***地方,则这个***既是门卫室的地址,也是整栋大楼的地址,它们的值相等,但是表示的意思不一样,这就解释了为什么a和&a都等于0xbff7aadc,而sizeof(a)等于20,sizeof(&a)却等于4,因为&a是一个指针变量,32位机下的都是占4个字节,由此,我们可以推出对于一位数组buf[],我们想求出里面元素的个数可以使用sizeof(buf) / sizeof(buf[0])。
对于a+1和&a+1,a+1则是第二个元素即a[1]的地址,这里的1表示一个数组单元,0xbff7aadc+4=0xbff7aae0;&a+1则是a[4]的下一个地址,此时的1表示的整个数组单元, 0xbff7aadc+4*5=0xbff7aaf0。
大家会有疑问,我们数组是a[5],应该最大为a[4],怎么会有a[5],a[10]啊?为什么没有产生溢出?因为在整个数组中我们只是申请了5个单元,虽然这5个单元后面的空间我们无法访问,但是,这些空间还是实实在在存在的啊!所以还是有地址的!
还有一点要注意,sizeof(a+1)和sizeof(&a+1)的值均为4,大家想想为什么?
4.下面的程序是实现简单的求m到n之间的素数,大家看看吧!
# include <stdio.h>
int prime(int n)
{
int i,j;
for(i=2;i<=n; i++)
if(n%i==0)
break;
if(i==n)
return 1;
else
return 0;
}
int main()
{
int i,j,m,n;
printf("Please input the Prime min and max limitation you want tocalculate: ");
scanf("%d,%d",&m,&n);
printf("The Prime of %d to %d limitation are ",m,n);
for(i=m;i<=n; i++)
if(prime(i))
printf("%d ",i);
printf("\n");
return 0;
}
打印:
5.大家说说,浮点数能进行自增和自减运算吗?答案是肯定的,不信?我们做个实例测试一下。
# include <head.h>
int main(int argc, const char *argv[])
{
float i = 1.0;
double j = 2.0;
printf("i=1.0,++i= %f,j-- = %f\n",++i,j--);
return 0;
}
打印: