今天在写一个简单的面向连接的TCP Socket程序时(UNIX Network Programming上的时间服务器和客户端例子)。有个简单的改变是将从服务器返回的日期字符串 改成一个字符一个字符的返回。
修改之前是这样子的:
//
ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
if( write(connfd, buff, strlen(buff)) < 0)
perror("write error\n");
buff是一个字符数组,其定义为:char buff[MAXLINE];
write 函数的第二个参数需要传递 char *类型的数据。这里将字符数组赋值给char *或者传递给char *是正确的。
需要注意的是sizeof(buff)的数值时MAXLINE而strlen(buff)的数值是其实际占用的空间(字符数且不包括最后的AISCII码为0 的'\0')。
那么如何将一个字符传递给write函数呢?
学习过C语言,我们知道buff指向的是buff字符数组第一个字符。也就是说假如buff的内容是"I am Chinese" ,则(*buff)的值为I,同理(buff+i)指向的是buff字符数组中的第i个字符。
于是下面的代码可以完成一个字符一个字符传递给write的功能:
int i = 0;
char * s = "I am Chinese";
while( *(s+i) != '\0') {
if( write(connfd, s+i, 1) < 0)
perror("write error\n");
i ++;
}
请注意,write的第二个参数s+i是一个地址。该地址是“I am Chinese”的第一个字符I的地址(或者指针)。第三个参数1表示由write写进s+i地址开始的1个字符。
/*-----------------------*/
在继续看下面的程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
char c[20] ="I am Chinese";
char c1[20] = {'H','E',' ','I','S',' ','A',' ','B','O','Y'};
printf("c is :%s, the sizeof c is: %d, the strlen of c is: %d\n", c, sizeof(c), strlen(c));
printf("c1 is :%s, the sizeof c1 is: %d, the strlen of c1 is: %d\n", c1, sizeof(c1), strlen(c1));
int i = 0;
for(i = 0; c[i] != 0; i ++) /* c[i] !='\0'起到的效果是一致的*/
printf("%c\n",c[i]);
return 0;
}
该程序的输出结果是:
c is :I am Chinese, the sizeof c is: 20, the strlen of c is: 12
c1 is :HE IS A BOY, the sizeof c1 is: 20, the strlen of c1 is: 11
I
a
m
C
h
i
n
e
s
e
该例子再一次的阐述了sizeof和strlen的区别。
假如将两个字符数组的声明修改成下面的方式:
char c[] ="I am Chinese";
char c1[] = {'H','E',' ','I','S',' ','A',' ','B','O','Y'};
printf("c is :%s, the sizeof c is: %d, the strlen of c is: %d\n", c, sizeof(c), strlen(c));
printf("c1 is :%s, the sizeof c1 is: %d, the strlen of c1 is: %d\n", c1, sizeof(c1), strlen(c1));
其运行结果是:
c is :I am Chinese, the sizeof c is: 13, the strlen of c is: 12
c1 is :HE IS A BOYI am Chinese, the sizeof c1 is: 11, the strlen of c1 is: 23
I
a
m
C
h
i
n
e
s
e
需要注意的是the sizeof c is: 13, the strlen of c is: 12,其原因就是最后有个'\0'占一个字符空间。
但是c1的输出结果有点神奇。。。
下面的例子更加的阐述了字符数组(字符串),指向字符串的指针与字符的关系
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
char c[20] ="I am Chinese";
char c1[30] = {'H','E',' ','I','S',' ','A',' ','B','O','Y'};
printf("c is :%s, the sizeof c is: %d, the strlen of c is: %d\n", c, sizeof(c), strlen(c));
printf("c1 is :%s, the sizeof c1 is: %d, the strlen of c1 is: %d\n", c1, sizeof(c1), strlen(c1));
int i = 0;
for(i = 0; c[i] != 0; i ++)
printf("%c\n",c[i]);
printf("from third element of char-array c is : %s\n", c+2);
int j = 0;
char c2[] = "hello world!";
char c3[30];
for(j =0; *(c2+j) != '\0'; j++)
*(c3+j) = *(c2+j);
*(c3+j) = 0;
printf("c3 is :%s\n", c3);
char *c4 = "I am serving on char";
char c5[50];
int k = 0;
while(*(c4+k) != 0) {
*(c5+k) = *(c4+k);
k ++;
}
*(c5+k) = '\0';
printf("c5 is :%s\n", c5);
return 0;
}
该程序的输出是:
c is :I am Chinese, the sizeof c is: 20, the strlen of c is: 12
c1 is :HE IS A BOY, the sizeof c1 is: 30, the strlen of c1 is: 11
I
a
m
C
h
i
n
e
s
e
from third element of char-array c is : am Chinese
c3 is :hello world!
c5 is :I am serving on char
还需要注意的是不建议使用下面这种声明 char c[] = "I am Chinese",而是使用char c[30] = "I am Chinese";也不建议使用char * str; 而是建议使用char str[100]这种声明。其原因是c[] 或者 *str这种使得程序在运行是往往不知道会访问到内存的哪里去。因为编译器并不知晓你需要多大的空间,很有可能这些变量在处理的过程中会将以c或者str开始的内存块访问到不该访问的区域去。