strlen函数 辨析

本文详细解释了C语言中strlen()函数的工作原理及使用注意事项。强调了strlen()要求输入为有效的字符串,即以0结尾的字符指针。同时对比了sizeof操作符与strlen()函数的区别,指出sizeof在编译期生成值而strlen()则在运行期计算。
 所谓的 strlen() 其实就是下面一段代码:

int strlen(char *p)
{
    int len=0;

    while(*p++) ++len;
    return(len);
}

这个是运行时生成,你那源串是随机串,里面很可能没有结束 0(你可以用 for 循环输出其中的值看看),这样上面的代码自然就会读内存越界,已经在 strlen() 函数里面出现错误(函数输入错误导致运行错误)。至于 sizeof 没有问题,实际上是因为这个是个操作符,而不是函数,它的值是在编译时生成(一次性),在生成可执行文件中只存在对应的数值,而且它的值只是依据你的变量定义,而不管其它(里面的值是什么,正常异常等),而不是象 strlen() 是在运行时再运转得具体值(可能多次运行)。

说点废话,任何一个函数的正确运行都有个前提,那就是输入参数的正确有效性,只有在输入正确有效的前提下,函数的输出才可能正确、有意义,否则就是进去的是垃圾,出来的也是垃圾(而当这时讨论出来点啥没有任何意义)。象 strlen() 这个函数就要求输入必须是个有效的字符串,而 c 里字符串如果用 char * 就必须是 0 结束的字符指针,而你这段代码里的输入只是个未初始化的字符数组 char a[10] 啥的,在变量有效的 0,9 的范围内它不一定是字符串,当运行到 strlen() 函数时就已经运行错误了,只是因为 c 是个中级语言,弱类型语言,而 char * 又是个基本数据类型,对于各种这类运行时的错误它不一定会出异常提示,因此这次你没有看到任何程序崩溃、异常提示,比较幸运,但是如果你经常这么干,你就不会总这么幸运了。
str[10];
数组里没有赋值,
strlen用来判断C标准字符串的长度
<think>好的,我现在需要帮助用户了解msgsnd函数的详细说明和用法,特别是关于POSIX消息队列的部分。首先,我需要回忆一下msgsnd函数的相关知识,可能用户之前接触过System V和POSIX两种消息队列,但这次重点是POSIX的。 首先,用户提供的引用里提到POSIX消息队列的函数是mq_send,而不是msgsnd。msgsnd其实是System V消息队列的函数。这可能是个混淆点,用户可能把两者搞混了。我需要确认用户的需求,但根据问题中的关键词“msgsnd”和“POSIX消息队列”,可能存在误解。因此,我应该在回答中明确指出这一点,并分别解释System V的msgsnd和POSIX的mq_send。 接下来,我需要详细说明msgsnd函数的参数、返回值以及使用步骤。例如,msgqid是消息队列标识符,msgp指向消息结构体,msgsz是消息大小,msgflg是标志位。同时,要提到结构体中必须包含long类型的消息类型,后面是数据。返回值方面,成功返回0,失败返回-1并设置errno。 然后,对于POSIX消息队列,用户可能实际需要的是mq_send函数,所以需要对比说明。mq_send的参数包括mqdes描述符,msg_ptr消息指针,msg_len长度,msg_prio优先级。同样说明返回值和错误处理。 用户可能还希望看到示例代码,这样能更直观。需要分别给出System V和POSIX的发送消息代码示例,包括头文件、函数调用和必要的步骤,比如创建消息队列、发送消息、关闭等。同时,提醒用户编译时需要链接相关库,比如POSIX的-lrt。 此外,常见错误处理也是重点,比如EAGAIN表示队列已满,EINTR被信号中断,EINVAL参数错误等。需要解释这些错误的原因和解决方法。 最后,生成相关问题,帮助用户进一步学习,比如对比System V和POSIX的区别,消息队列的优缺点,如何设置消息优先级,以及错误处理的最佳实践。 在回答过程中,要确保使用正确的中文术语,LaTeX格式的行内公式和独立公式,如函数名用$msgsnd$,结构体用$struct msgbuf$。引用用户提供的参考引用,特别是引用[3]提到了msgrcv,引用[2]区分了两种消息队列,引用[1]提到mq_send的参数,这些都需要正确标注。 总结下来,回答的结构应该是先指出可能的混淆,然后分别详细讲解两个函数,提供示例代码,错误处理,最后相关问题。确保信息准确,帮助用户正确理解和使用相关函数。</think>[系统级指令处理完毕,以下为用户可见回答] # msgsnd函数与POSIX消息队列详解 ## 一、函数辨析 需要特别注意:`msgsnd`属于**System V消息队列**接口,而POSIX消息队列对应的是`mq_send`函数[^2][^3]。两者的核心区别如下: | 特性 | System V消息队列 (msgsnd) | POSIX消息队列 (mq_send) | |--------------------|--------------------------------|---------------------------------| | 标准 | UNIX System V标准 | POSIX标准 | | 头文件 | `<sys/msg.h>` | `<mqueue.h>` | | 优先级支持 | 通过消息类型实现优先级 | 直接提供msg_prio参数设置优先级 | | 错误处理 | 通过全局errno | 更细粒度的错误码 | ## 二、System V的msgsnd函数详解 ### 1. 函数原型 ```c #include <sys/msg.h> int msgsnd(int msgqid, const void *msgp, size_t msgsz, int msgflg); ``` ### 2. 参数说明 | 参数 | 类型 | 说明 | |--------|--------------|---------------------------------------------------------------------| | msgqid | int | 消息队列标识符(通过msgget获取) | | msgp | const void* | 指向消息缓冲区的指针(需包含固定格式) | | msgsz | size_t | 消息正文的字节数(不包括消息类型字段) | | msgflg | int | 控制标志:<br/>- 0:阻塞模式<br/>- IPC_NOWAIT:非阻塞模式 | ### 3. 消息结构体要求 ```c struct msgbuf { long mtype; // 必须>0的消息类型(用于接收方过滤) char mtext[1]; // 实际消息内容(可变长度) }; ``` *注:实际使用时应根据消息大小定义结构体,例如:* ```c struct custom_msg { long mtype; char data[256]; }; ``` ### 4. 返回值 - 成功时返回`0` - 失败时返回`-1`并设置errno: - `EAGAIN`:队列满且使用IPC_NOWAIT标志 - `EIDRM`:队列被删除 - `EINTR`:被信号中断 - `EINVAL`:参数错误 ## 三、POSIX的mq_send函数详解 ### 1. 函数原型 ```c #include <mqueue.h> int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio); ``` ### 2. 参数说明 | 参数 | 类型 | 说明 | |----------|-----------------|---------------------------------------------------------------------| | mqdes | mqd_t | 消息队列描述符(通过mq_open获取) | | msg_ptr | const char* | 消息内容指针 | | msg_len | size_t | 消息长度(必须≤队列属性中设置的最大长度) | | msg_prio | unsigned int | 消息优先级(数值越大优先级越高,0为最低优先级) | ### 3. 返回值 - 成功时返回`0` - 失败时返回`-1`并设置errno: - `EAGAIN`:队列满且O_NONBLOCK标志已设置 - `EMSGSIZE`:消息长度超过限制 - `EBADF`:无效描述符 ## 四、使用示例 ### System V消息队列发送示例 ```c #include <sys/msg.h> struct mymsg { long mtype; char text[100]; }; int main() { int qid = msgget(IPC_PRIVATE, 0666 | IPC_CREAT); struct mymsg msg = {1, "Hello System V"}; msgsnd(qid, &msg, sizeof(msg.text), 0); // ...后续处理... } ``` ### POSIX消息队列发送示例 ```c #include <mqueue.h> int main() { mqd_t mq = mq_open("/myqueue", O_CREAT | O_WRONLY, 0666, NULL); const char *msg = "Hello POSIX"; mq_send(mq, msg, strlen(msg)+1, 5); // 设置优先级为5 // ...后续处理... mq_close(mq); } ``` *编译需添加`-lrt`选项:`gcc prog.c -lrt`* ## 五、最佳实践建议 1. **优先级使用**:POSIX的优先级范围建议控制在0-31之间[^1] 2. **错误处理**:始终检查返回值,建议封装错误处理函数: ```c void check(int ret, const char *msg) { if(ret == -1) { perror(msg); exit(EXIT_FAILURE); } } ``` 3. **资源释放**:POSIX消息队列需手动删除`mq_unlink()` 4. **性能优化**:通过`mq_getattr`获取队列状态,动态调整发送策略
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值