C语言void函数调用OpenCL接口时无法更新主函数变量值问题
问题根因
核心问题是C语言的值传递机制:
- 你定义的
getcldeviceinfo函数中,cl_uint ndev是值类型形参,函数被调用时,会为这个形参单独开辟内存空间,拷贝main函数中传入的ndev值到这块独立内存。函数内部对ndev的所有修改,都只作用在这份拷贝上,函数返回后这份拷贝就会被销毁,完全不会影响main函数里的原始ndev变量,这就是main中打印值一直是初始值0的原因。 - 代码中还有一处不影响核心逻辑但可能触发编译问题的笔误:头文件前的版本宏写成了
CL_TARGET_OPPENCL_VERSION,正确拼写是CL_TARGET_OPENCL_VERSION。 - 你可能会疑惑为什么
devs数组能正常被函数修改:因为C语言中数组作为形参传递时,会自动退化为指向数组首地址的指针,函数内对数组元素的操作是直接访问原内存空间,不存在值拷贝,所以不需要额外加指针就能回写内容。
修正方法
只需要把ndev参数改为指针传递,让函数可以直接操作main中原始变量的内存即可,具体修改点:
- 修正OpenCL版本宏的拼写错误
- 将
getcldeviceinfo的形参cl_uint ndev改为指针类型cl_uint *ndev - 函数内部所有读取、修改
ndev值的位置,改为对指针解引用(即*ndev),注意传给clGetDeviceIDs用于接收设备数量的参数本身就需要指针类型,这里直接传ndev即可 - main函数调用
getcldeviceinfo时,把原来传入的ndev改为传入ndev的地址&ndev
修正后的完整可运行代码:
#include <stdio.h> #include <stdlib.h> #define CL_TARGET_OPENCL_VERSION 200 #include <CL/cl.h> void getcldeviceinfo(int plfn, int dev_type, cl_uint *ndev, cl_device_id devs[]) { cl_int cle; cl_uint nplf; cl_platform_id plfs[2]; // 获取平台数量和平台ID cle = clGetPlatformIDs(0, NULL, &nplf); cle = clGetPlatformIDs(nplf, plfs, NULL); if (cle != CL_SUCCESS || nplf <= 0) { printf("Failed to find any OpenCL platforms\n"); } // 获取指定平台下的设备数量和设备ID if (dev_type != 0) { cle = clGetDeviceIDs(plfs[plfn], CL_DEVICE_TYPE_CPU, 0, NULL, ndev); cle = clGetDeviceIDs(plfs[plfn], CL_DEVICE_TYPE_CPU, *ndev, devs, NULL); } else { cle = clGetDeviceIDs(plfs[plfn], CL_DEVICE_TYPE_GPU, 0, NULL, ndev); cle = clGetDeviceIDs(plfs[plfn], CL_DEVICE_TYPE_GPU, *ndev, devs, NULL); } printf("number of devices inside the function : %u\n", *ndev); } int main(int argc, char** argv) { cl_device_id devices[10]; cl_uint ndev = 0; printf("number of devices inside the main function before : %u\n",ndev); getcldeviceinfo(0, 0, &ndev, devices); printf("number of devices inside the main function after : %u\n",ndev); return 0; }
编译运行后即可得到预期输出:
number of devices inside the main function before : 0 number of devices inside the function : 2 number of devices inside the main function after : 2
内容的提问来源于stack exchange,提问作者Redshoe
相关产品推荐
相关产品推荐

