Linux使用strlen编译,Linux write与printf,strlen与sizeof使用须知

注意到此二者的差异源于《Unix环境高级编程》一书8.3章节fork function。

示例程序

注意自行验证时,应注释掉apue.h包含,自行实现err_sys函数,以及包含缺乏的头文件,即可编译过。下面是经过书中示例修改后的代码,linux下可以编译运行

//#include "apue.h"

#include "unistd.h"

void err_sys(char * errinfo)

{

printf("Error: %s\n", errinfo);

exit(-1);

}

int globvar = 6; /* external variable in initialized data */

char buf[] = "a write to stdout\n";

int main(void)

{

int var; /* automatic variable on the stack */

pid_t pid;

var = 88;

if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)

err_sys("write error");

printf("before fork\n"); /* we don’t flush stdout */

if ((pid = fork()) < 0) {

err_sys("fork error");

} else if (pid == 0) { /* child */

globvar++; /* modify variables */

var++;

} else {

sleep(2); /* parent */

}

printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar,var);

exit(0);

}

程序运行结果 前者为直接运行的打印结果,后者为程序输出重定向到文件后的运行打印结果:

$./a.out

a write to stdout

before fork

pid = 430, glob = 7, var = 89 #child’s variables were changed

pid = 429, glob = 6, var = 88 #parent’s copy was not changed

$ ./a.out > temp.out

$ cat temp.out

a write to stdout

before fork

pid = 432, glob = 7, var = 89

before fork

pid = 431, glob = 6, var = 88

sizeof与strlen

When we write to standard output, we subtract 1 from the size of buf to avoid

writing the terminating null byte. Although strlen will calculate the length of a string

not including the terminating null byte, sizeof calculates the size of the buffer, which

does include the terminating null byte. Another difference is that using strlen

requires a function call, whereas sizeof calculates the buffer length at compile time, as

the buffer is initialized with a known string and its size is fixed.

示例程序中write函数写入字符串时计算长度使用的是sizeof,并且减去1,去掉字符串末尾的空字符,避免write函数写空字符(相当于没有写入内容);实际也可以直接使用strlen(buf),等价于sizeof(buf) -1。

sizeof是运算符,在编译时即可计算出结果

strlen是函数,使用时存在函数调用开销

char *buf1 = “abcdef”,sizeof(buf1) 结果是4 指针自身占用的内存字节数,而非指向内容所占字节数;

strlen 使用时,所用对象必须是‘/0’结束

write 与 printf

the write function is not buffered. Because write is called

before the fork, its data is written once to standard output. The standard I/O library,

however, is buffered.standard output is line buffered if it’s

connected to a terminal device; otherwise, it’s fully buffered.

When we run the

program interactively, we get only a single copy of the first printf line, because the

standard output buffer is flushed by the newline. When we redirect standard output to

a file, however, we get two copies of the printf line. In this second case, the printf

before the fork is called once, but the line remains in the buffer when fork is called.

This buffer is then copied into the child when the parent’s data space is copied to the

child. Both the parent and the child now have a standard I/O buffer with this line in it.

The second printf, right before the exit, just appends its data to the existing buffer.

When each process terminates, its copy of the buffer is finally flushed

write 函数是字节流写入,无缓存的,即每次调用,即立即写入所有内容

printf 函数是有缓存的,当标准输出是终端时,为行缓存方式,遇到换行或者行缓存满时,才真正输出打印;当标准输出非终端时,如上面的示例中重定向到文件,其一直处于缓存状态,直到程序结束时触发flush,才输出到文件。(因为fork创建的子进程会复制父进程的内存内容,创建自己的地址空间,由于重定向到文件时,printf函数的内容仍在缓存中,所以会看到两次的before fork 打印)

上述示例程序中若在printf("before fork\n")后立即调用fflush(STDOUT_FILENO)将标准输出的缓存立即输出打印,则上面第二次重定向输出到文件时的结果与第一次一样

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值