C语言数组指针使用问题:求集合差集时出现警告及无输出
集合差集计算程序的问题分析与修正
问题概述
我正在编写一个程序,用于读取两个集合并计算它们的差集(存在于集合A但不存在于集合B的元素)。集合用0和1组成的数组存储(1表示元素存在,0表示不存在)。但代码出现以下警告,且无法返回正确结果:
warning: comparison between pointer and integer [enabled by default]
if(p1 && q0)
^
warning: assignment makes pointer from integer without a cast [enabled by default]
set_difference = 1;
原代码如下:
#define N 10 void find_set_difference(int *set_a, int *set_b, int n, int *set_difference); int main(void) { int i, k; int n; printf("Enter the number of elements in set A: \n"); scanf("%d", &n); int a[n]; printf("Enter the elements in set A: \n"); for(i=0; i<n; i++){ scanf("%d", &a[k]); a[k] = 1; } printf("Enter the number of elements in set B: \n"); scanf("%d", &n); int b[n]; printf("Enter the elements in set B: \n"); for(i=0; i<n; i++){ scanf("%d", &b[k]); b[k] = 1; } int set_dif[N]; find_set_difference(a, b, N, set_dif); printf("The difference of set A and set B is: \n"); for(i=0;i<10;i++){ if(set_dif[i]==1) printf("%d ",i); } return 0; } void find_set_difference(int *set_a, int *set_b, int n, int *set_difference){ int *p, *q; for(p=set_a; p<set_a+n; p++){ for(q=set_b; q<set_b+n; q++){ if(p==1 && q==0) set_difference = 1; else set_difference = 0; } } }
警告原因解析
- 指针与整数比较警告:
p和q是指针变量,存储的是数组元素的内存地址,直接和整数1、0比较属于非法操作。你需要访问指针指向的元素值,应该使用*p(解引用指针)来获取对应元素的值。 - 指针赋值整数警告:
set_difference是指向结果数组的指针,直接给它赋值整数1,相当于把指针的内存地址设置为1,这完全不符合逻辑。你需要给指针指向的数组元素赋值,应该通过下标或指针偏移来访问对应位置。
代码错误逐一修正
1. main函数中的错误
- 未初始化变量
k:k未赋值就用来作为数组下标,会导致随机访问内存,直接删除k,改用输入的元素编号作为下标。 - 数组未初始化:定义集合数组后,先将所有元素初始化为0,再根据输入的元素编号设置为1。
- 重复使用变量
n:用n_a存储集合A的元素个数,n_b存储集合B的元素个数,避免覆盖。 - 结果数组初始化:将
set_dif的所有元素初始化为0,确保未被标记的元素为0。 - 元素范围校验:添加输入元素的范围判断,避免超出数组下标范围。
2. find_set_difference函数中的错误
- 双重循环逻辑错误:差集的逻辑是逐个下标判断:如果集合A对应位置为1,且集合B对应位置为0,则结果数组对应位置为1。只需要单循环遍历每个下标即可。
- 指针使用错误:用
*p访问集合A的元素,通过指针偏移计算下标,访问集合B和结果数组的对应位置。
修正后的完整代码
#define N 10 void find_set_difference(int *set_a, int *set_b, int n, int *set_difference); int main(void) { int i, elem; int n_a, n_b; // 初始化集合A printf("Enter the number of elements in set A: \n"); scanf("%d", &n_a); int a[N] = {0}; // 初始化为全0 printf("Enter the elements in set A (0-%d): \n", N-1); for(i=0; i<n_a; i++){ scanf("%d", &elem); if(elem >=0 && elem < N){ // 确保元素在合法范围内 a[elem] = 1; } } // 初始化集合B printf("Enter the number of elements in set B: \n"); scanf("%d", &n_b); int b[N] = {0}; // 初始化为全0 printf("Enter the elements in set B (0-%d): \n", N-1); for(i=0; i<n_b; i++){ scanf("%d", &elem); if(elem >=0 && elem < N){ // 确保元素在合法范围内 b[elem] = 1; } } int set_dif[N] = {0}; // 结果数组初始化为全0 find_set_difference(a, b, N, set_dif); printf("The difference of set A and set B is: \n"); for(i=0; i<N; i++){ if(set_dif[i] == 1){ printf("%d ", i); } } printf("\n"); return 0; } void find_set_difference(int *set_a, int *set_b, int n, int *set_difference){ int *p; // 遍历每个下标位置 for(p = set_a; p < set_a + n; p++){ int index = p - set_a; // 计算当前元素的下标 // 差集逻辑:A存在,B不存在 if(*p == 1 && set_b[index] == 0){ set_difference[index] = 1; } else { set_difference[index] = 0; } } }
指针使用基础提示
- 指针变量存储的是内存地址,不是元素值,要获取元素值必须用
*指针(解引用操作)。 - 数组名本质是指向数组第一个元素的指针,比如
a等价于&a[0]。 - 指针可以进行加减运算:
p++会让指针移动到下一个同类型元素的地址,p - set_a可以计算出当前指针对应的数组下标。 - 操作数组时必须注意边界,避免访问超出数组范围的内存,否则会导致程序崩溃或异常结果。
内容的提问来源于stack exchange,提问作者awsumbakugan
相关产品推荐
相关产品推荐

