使用指针遍历Viewer数组遇空指针,如何正确迭代?
问题:C语言指针遍历Viewer数组时第二次迭代指针为空的原因及修复
我用C写了个统计指定视频观看次数的代码,想用指针遍历Viewer数组,但第一次迭代正常,第二次迭代时ptr指针就指向空了。不确定ptr++是不是适合这种场景,想知道正确的数组迭代方式。代码如下:
#include<stdio.h> #include<stdlib.h> #include<string.h> // 后续用strcmp需要加这个头文件 typedef struct Video { char *name; int unique_views; } Video; typedef struct Viewer { char *username; Video *watched_videos; int watched_videos_size; } Viewer; int count_views(Viewer **viewers, int viewers_size, char *video_name) { Viewer *ptr; Video *vid; int count=0; ptr = *viewers; for (int i=0;i< viewers_size;i++){ printf("%s ",ptr->username); vid=ptr->watched_videos; for (int j=0;j < ptr->watched_videos_size;j++){ printf("%d %d",j,ptr->watched_videos_size); printf("%s\n",vid->name); if (vid->name == video_name){ count++; } vid++; } ptr++; } return count; } int main() { Video videos[] = { {.name = "Soccer", .unique_views = 500}, {.name = "Basketball", .unique_views = 1000} }; Video videos2[] = { {.name = "Soccer", .unique_views = 500} }; Viewer viewer = {.username = "Dave", .watched_videos = videos, .watched_videos_size = 2} ; Viewer view = {.username = "Bob", .watched_videos = videos2, .watched_videos_size = 1}; Viewer *viewers[] = { &viewer, &view }; printf("%d", count_views(viewers, 2, "Soccer")); /* should print 1 */ }
核心问题分析
你的ptr++之所以失效,是因为**viewers是一个Viewer*类型的指针数组**,而非连续的Viewer结构体数组:
main里定义的Viewer *viewers[] = { &viewer, &view };,存的是两个指向独立Viewer结构体的指针,这两个指针的内存地址并不连续(viewer和view是栈上的两个独立变量,地址无连续性)。- 当你执行
ptr = *viewers拿到第一个指针后,ptr++会把指针地址增加sizeof(Viewer),但这个新地址并不是第二个Viewer*的地址,而是跑到了无效内存区域,导致第二次迭代时ptr指向空或垃圾值。
正确的迭代方式
写法1:下标访问指针数组(最直观)
直接通过viewers[i]获取每个Viewer*,避免指针操作出错:
int count_views(Viewer **viewers, int viewers_size, char *video_name) { Video *vid; int count=0; for (int i=0;i< viewers_size;i++){ Viewer *ptr = viewers[i]; // 直接取数组内的指针 printf("%s ",ptr->username); vid=ptr->watched_videos; for (int j=0;j < ptr->watched_videos_size;j++){ printf("%d %d ",j,ptr->watched_videos_size); printf("%s\n",vid->name); // 字符串比较用strcmp,而非== if (strcmp(vid->name, video_name) == 0){ count++; } vid++; } } return count; }
写法2:二级指针遍历指针数组
如果坚持用指针遍历,直接操作传入的二级指针viewers:
int count_views(Viewer **viewers, int viewers_size, char *video_name) { Video *vid; int count=0; Viewer **ptr = viewers; // 二级指针指向指针数组起始 for (int i=0;i< viewers_size;i++){ Viewer *current_viewer = *ptr; // 取出当前Viewer指针 printf("%s ",current_viewer->username); vid=current_viewer->watched_videos; for (int j=0;j < current_viewer->watched_videos_size;j++){ printf("%d %d ",j,current_viewer->watched_videos_size); printf("%s\n",vid->name); if (strcmp(vid->name, video_name) == 0){ count++; } vid++; } ptr++; // 二级指针++,指向数组内下一个Viewer* } return count; }
额外修复点
- 字符串比较错误:原代码用
vid->name == video_name是比较指针地址,而非字符串内容,必须用strcmp函数(需包含<string.h>)。 - 头文件错误:C语言用
#include而非#import,后者是Objective-C语法。 - printf格式问题:原代码换行符位置错误,改为
printf("%s\n",vid->name);。
内容的提问来源于stack exchange,提问作者Anshal Antony
相关产品推荐
相关产品推荐

