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

C语言中如何将自定义类型静态数组传参给另一个自定义对象

问题描述

我在C语言中尝试将自定义类型的静态数组传递给另一个自定义结构体,定义了如下结构体:

typedef struct sem_holder
{
    sem_t *writer_sem;
    sem_t *reader_sem;
} sem_holder;

typedef struct worker_arg
{
    unsigned int nsegments;
    size_t segsize;
    sem_holder *sems;
} worker_arg;

最初传递sems数组时遇到指针类型不匹配的编译错误:

  • 使用&sems时,提示初始化sem_holder*类型不兼容;
  • 使用sems时,提示sem_holder*与sem_holder**类型不兼容。

修改代码后传参成功,但调用sem_open初始化信号量时设置初始值为10,实际运行时信号量值始终为0,求解决思路。修改后的代码如下:

// char *processes[nsegments];
sem_holder sems[nsegments];
char sem_write_name[21];
char sem_read_name[21];
sem_t *writer_sem;
sem_t *reader_sem;

ftruncate(DATA_CHANNEL_ID, segsize * nsegments);
for (int i = 0; i < nsegments; i++)
{
    // Map subsection of data-channel to an array in proxy's virtual memory
    // processes[i] = mmap(NULL, sizeof(segsize), PROT_READ | PROT_WRITE, MAP_SHARED, DATA_CHANNEL_ID, i * segsize);

    // Dynamically create reader and writer names
    snprintf(sem_write_name, 21, "%dw", i);
    snprintf(sem_read_name, 21, "%dr", i);

    // Create a likewise array for semaphores
    writer_sem = sem_open(sem_write_name, O_CREAT, 0660, 10);
    if (writer_sem == SEM_FAILED)
      printf("FAILED\n");
    sems[i].writer_sem = writer_sem;

    reader_sem = sem_open(sem_read_name, O_CREAT, 0660, 10);
    if (reader_sem == SEM_FAILED)
      printf("FAILED\n");
    sems[i].reader_sem = reader_sem;
}

// Initialize worker arg
worker_arg worker_arg = {.nsegments = nsegments, .segsize = segsize, .sems = sems};
解决思路

一、数组传参类型问题的说明

静态数组sems[nsegments]的数组名sems会隐式转换为指向数组首元素的指针,类型是sem_holder*,和worker_arg的sems成员类型完全匹配。你最初碰到的类型不兼容错误,大概率是之前误将worker_arg的sems成员定义为sem_holder**,或者传参时多取了一次地址。现在修改后的代码里.sems = sems的写法是完全正确的,不需要加&。

二、信号量初始值异常的排查步骤

  1. 检查信号量是否已存在:sem_open仅在信号量不存在时才会使用你传入的初始值。如果之前运行程序时创建过同名信号量且未清理,O_CREAT标志会直接打开现有信号量,忽略初始值。
    • 处理方案:
      • 在sem_open中添加O_EXCL标志(即O_CREAT | O_EXCL),这样如果信号量已存在会直接报错,方便快速定位;
      • 程序退出时,先调用sem_close关闭信号量,再调用sem_unlink删除命名信号量,避免残留;
      • 手动清理系统中已存在的同名信号量(用ipcs命令查看,ipcrm命令删除)。
  2. 完善错误日志:当前代码仅打印"FAILED",无法定位具体错误原因。建议替换为perror("sem_open failed"),这样可以输出系统错误信息,确认信号量是否真的创建成功。
  3. 排查信号量操作逻辑:如果其他线程/进程在你检查信号量值之前执行了sem_wait操作,会将信号量计数减到0。要确保在读取信号量值前,没有对其进行P操作。
  4. 验证权限设置:0660的权限是否符合当前进程的运行上下文?如果权限不足,可能导致信号量访问异常,不过这种情况通常sem_open会直接失败,通过perror可以快速排查。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 19:45:39