You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复C/Unix程序中“assignment makes pointer from integer without a cast”警告

问题分析与修复方案

嘿,我帮你找到了问题的根源——这是C语言里很容易踩的运算符优先级坑!你的编译警告和段错误都是因为这个,咱们一步步来解决:

1. 编译警告与段错误的核心原因

在C语言中,==(相等判断)的优先级比=(赋值)高,所以你写的这类代码:

if(id_mem = shmget(key_mem,SHMEMSIZE,0) == -1)

实际执行顺序完全不是你想的那样:它会先计算shmget(...) == -1,得到一个布尔值(0或1,属于整数类型),然后把这个整数赋值给id_mem。

这直接导致两个严重问题:

  • id_mem拿到的不是正确的共享内存ID,而是0或1,后续用这个错误ID调用shmat,返回的地址肯定无效,自然触发段错误
  • 对于addr_mem = shmat(...) == (void*)-1,同样是把布尔值(整数)赋值给指针类型的addr_mem,所以编译器会抛出“assignment makes pointer from integer without a cast”的警告

2. 最关键的修复:加括号改变优先级

所有这类“赋值+判断”的语句,都要给赋值表达式套上括号,确保先完成赋值,再判断结果是否为-1:

生产者代码的修复点

把原来的:

if(id_mem = shmget(key_mem,SHMEMSIZE,0) == -1)
if(addr_mem =shmat(id_mem,NULL,0) == (void *)-1)
if(id_sem = semget(key_sem,2,0)== -1)

改成:

if( (id_mem = shmget(key_mem,SHMEMSIZE,0)) == -1 )
if( (addr_mem = shmat(id_mem,NULL,0)) == (void *)-1 )
if( (id_sem = semget(key_sem,2,0)) == -1 )

消费者代码的修复点

同样修复优先级问题,比如:

// 修复前
if(id_mem = shmget(key_mem,SHMEMSIZE,IPC_CREAT|0666) == -1)
// 修复后
if( (id_mem = shmget(key_mem,SHMEMSIZE,IPC_CREAT|0666)) == -1 )

另外,消费者里还有个小错误:shmctl(id_sem, IPC_RMID, NULL)是错的,shmctl是用来操作共享内存的,应该传入共享内存IDid_mem,而不是信号量IDid_sem,这个也要修正。

3. 额外的细节优化

  • 生产者里的scanf("%[^\n]", ...)容易被残留的换行符影响,改成scanf(" %[^\n]", ...)(注意前面的空格),可以自动跳过输入前的空白字符,避免直接按回车导致的异常
  • 原来的getc(stdin)可以去掉,因为上面的scanf已经处理了换行问题

修复后的完整代码

修复后的生产者代码

#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <stdio.h>
#define SHMEMSIZE 4096

int main() {
    key_t key_mem = 6868;
    key_t key_sem = 3232;
    int id_mem;
    int id_sem;
    void *addr_mem;
    struct sembuf param[1];

    // 修复运算符优先级:赋值表达式加括号
    if( (id_mem = shmget(key_mem, SHMEMSIZE, 0)) == -1 ) {
        perror("Errore1: 共享内存获取失败");
        return -1;
    }

    if( (addr_mem = shmat(id_mem, NULL, 0)) == (void *)-1 ) {
        perror("Errore2: 共享内存挂载失败");
        return -1;
    }

    if( (id_sem = semget(key_sem, 2, 0)) == -1 ) {
        perror("Errore3: 信号量获取失败");
        shmdt(addr_mem);
        return -1;
    }

    while(1) {
        // P操作:获取空缓冲区信号量
        param[0].sem_num = 1;
        param[0].sem_op = -1;
        param[0].sem_flg = 0;
        if(semop(id_sem, param, 1) == -1) {
            perror("Errore6: 信号量操作失败");
            return -1;
        }

        printf("Scrivi messaggio: ");
        // 前面加空格跳过空白字符,避免残留换行影响
        if( scanf(" %[^\n]", (char *)addr_mem) == 0 )
            *((char *)addr_mem) = '\0';

        // V操作:通知有数据可读取
        param[0].sem_num = 0;
        param[0].sem_op = 1;
        param[0].sem_flg = 0;
        if(semop(id_sem, param, 1) == -1) {
            perror("Errore7: 信号量操作失败");
            return -1;
        }
    }

    shmdt(addr_mem);
    return 0;
}

修复后的消费者代码

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <stdio.h>
#define SHMEMSIZE 4096

union semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
    struct seminfo *__buf;
};

int main() {
    key_t key_mem = 6868;
    key_t key_sem = 3232;
    int id_mem;
    int id_sem;
    void *addr_mem;
    union semun arg;
    struct sembuf param[1];

    // 修复运算符优先级
    if( (id_mem = shmget(key_mem, SHMEMSIZE, IPC_CREAT|0666)) == -1 ) {
        perror("Errore1: 共享内存创建失败");
        return -1;
    }

    if( (addr_mem = shmat(id_mem, NULL, 0)) == (void *)-1 ) {
        perror("Errore2: 共享内存挂载失败");
        shmctl(id_mem, IPC_RMID, NULL);
        return -1;
    }

    if( (id_sem = semget(key_sem, 2, IPC_CREAT|0666)) == -1 ) {
        perror("Errore3: 信号量创建失败");
        shmctl(id_mem, IPC_RMID, NULL);
        shmdt(addr_mem);
        return -1;
    }

    // 初始化数据就绪信号量(0:无数据)
    arg.val = 0;
    if(semctl(id_sem, 0, SETVAL, arg) == -1) {
        perror("Errore4: 信号量初始化失败");
        semctl(id_sem, -1, IPC_RMID, arg);
        shmctl(id_mem, IPC_RMID, NULL); // 修复:使用共享内存ID
        shmdt(addr_mem);
        return -1;
    }

    // 初始化空缓冲区信号量(1:有一个空缓冲区)
    arg.val = 1;
    if(semctl(id_sem, 1, SETVAL, arg) == -1) {
        perror("Errore5: 信号量初始化失败");
        semctl(id_sem, -1, IPC_RMID, arg);
        shmctl(id_mem, IPC_RMID, NULL); // 修复:使用共享内存ID
        shmdt(addr_mem);
        return -1;
    }

    while(1) {
        // P操作:等待数据就绪
        param[0].sem_num = 0;
        param[0].sem_op = -1;
        param[0].sem_flg = 0;
        if(semop(id_sem, param, 1) == -1) {
            perror("Errore6: 信号量操作失败");
            return -1;
        }

        printf("Il messaggio scritto è: %s\n", (char *)addr_mem);

        // V操作:释放空缓冲区
        param[0].sem_num = 1;
        param[0].sem_op = 1;
        param[0].sem_flg = 0;
        if(semop(id_sem, param, 1) == -1) {
            perror("Errore7: 信号量操作失败");
            return -1;
        }
    }

    // 理论上不会执行到这里,加上清理代码更严谨
    semctl(id_sem, -1, IPC_RMID, arg);
    shmctl(id_mem, IPC_RMID, NULL);
    shmdt(addr_mem);
    return 0;
}

运行步骤

  1. 先启动消费者程序:它会负责创建共享内存和信号量,并初始化信号量的初始值
  2. 再启动生产者程序:输入消息后,消费者会立刻输出你输入的内容

这样修复后,编译警告会消失,生产者也不会再触发段错误,共享内存可以正常完成读写操作啦!

内容的提问来源于stack exchange,提问作者ABC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:57:56