1. C语言循环基础实战指南
作为一名有十年C语言开发经验的程序员,我深知循环结构在编程中的重要性。循环不仅是代码复用的基础,更是算法实现的核心。本文将带你深入理解C语言中while和for循环的实战应用,通过20+个经典案例,帮你彻底掌握循环编程的精髓。
1.1 循环结构的选择与设计原则
在C语言中,我们主要使用while、do-while和for三种循环结构。选择哪种循环取决于具体场景:
- while循环:适合不确定循环次数的场景,如读取用户输入直到满足条件
- do-while循环:至少执行一次循环体,适合菜单选择等场景
- for循环:适合已知循环次数的场景,如遍历数组
重要提示:所有循环都必须确保有明确的终止条件,否则会导致无限循环。在开发环境中,可以使用Ctrl+C终止失控的程序。
1.2 基础累加算法实现
让我们从最简单的1到n累加开始,这是理解循环的经典案例:
c复制#include <stdio.h>
int main() {
int sum = 0, i = 1, n;
scanf("%d", &n); // 获取用户输入的n值
while (i <= n) {
sum += i; // 累加当前值
i++; // 计数器递增
}
printf("累加和为%d", sum);
return 0;
}
代码解析:
sum初始化为0,用于存储累加结果i从1开始,每次循环递增1,直到超过nsum += i是sum = sum + i的简写形式
优化技巧:
- 对于大数计算,可以使用
long或long long类型防止溢出 - 输入验证:应检查n是否为正整数
- 数学公式法:sum = n*(n+1)/2 效率更高,但循环法更具通用性
1.3 奇偶数的特殊处理
实际开发中,经常需要处理特定条件的数字。下面是计算1到n之间奇数和与偶数和的两个方案:
方案一:使用取模运算
c复制int n, i = 1, sum_odd = 0, sum_even = 0;
scanf("%d", &n);
while (i <= n) {
if (i % 2 != 0) // 奇数判断
sum_odd += i;
else // 偶数判断
sum_even += i;
i++;
}
方案二:利用数字特性
c复制// 奇数累加
int sum_odd = 0;
for (int i = 1; i <= n; i += 2) {
sum_odd += i;
}
// 偶数累加
int sum_even = 0;
for (int i = 2; i <= n; i += 2) {
sum_even += i;
}
性能对比:
- 方案一需要n次循环和n次条件判断
- 方案二只需n/2次循环,无条件判断,效率更高
- 方案一更灵活,可以同时处理多种条件
1.4 区间数字处理实战
处理任意区间[m,n]的数字时,需要先确保m ≤ n。这是一个典型的防御性编程案例:
c复制int n, m, sum = 0, temp;
scanf("%d %d", &n, &m);
// 确保n <= m
if (n > m) {
temp = n;
n = m;
m = temp;
}
// 计算区间内偶数之和
while (n <= m) {
if (n % 2 == 0)
sum += n;
n++;
}
关键点:
- 使用temp变量交换n和m的值
- 边界检查:包含m本身是否在计算范围内
- 可扩展性:同样的模式可用于其他条件筛选
2. 进阶循环算法解析
2.1 阶乘计算与数值溢出
阶乘是理解循环和数值范围的绝佳案例。n的阶乘表示为n!,是1到n所有整数的乘积。
c复制int n, i = 1, factorial = 1;
scanf("%d", &n);
while (i <= n) {
factorial *= i;
i++;
}
常见陷阱:
- 忘记初始化factorial为1(初始化为0会导致结果始终为0)
- 数值溢出:13!就会超出32位int的范围(2^31-1=2,147,483,647)
解决方案:
- 使用
unsigned long long类型(最大18,446,744,073,709,551,615) - 添加溢出检测:
c复制if (factorial > INT_MAX / i) { printf("警告:即将发生溢出!"); break; }
2.2 交替符号数列求和
计算1-2+3-4+...±n这类交替数列需要引入符号控制变量:
c复制int i = 1, sum = 0, sign = 1, n;
scanf("%d", &n);
while (i <= n) {
sum += i * sign;
sign = -sign; // 符号翻转
i++;
}
算法优化:
- 数学分析法:数列可分为奇数组和偶数组分别求和
- 观察规律:当n为偶数时,sum = -n/2;奇数时sum = (n+1)/2
2.3 数字位数处理技术
数字的位数处理是循环的典型应用,包括数位分离、逆序输出等:
逆序输出数字各位:
c复制int num;
scanf("%d", &num);
while (num != 0) {
int digit = num % 10; // 获取个位数
printf("%d", digit);
num /= 10; // 去掉已处理的个位
}
数位组合应用:
- 判断回文数
- 数字加密/解密
- 进制转换基础
2.4 综合案例:GDP增长预测
通过循环实现复利计算是金融计算的常见场景。假设初始GDP为10.5万亿美元,年增长3.2%:
c复制int year = 2025;
double gdp = 10.5; // 单位:万亿美元
while (year <= 2036) {
gdp *= (1 + 0.032);
printf("%d年GDP:%.2lf万亿美元\n", year, gdp);
year++;
}
关键点:
- 使用double类型保证精度
- 注意浮点数的累积误差问题
- 实际应用中应考虑通胀率变化等动态因素
3. 经典算法实现
3.1 最大公约数与最小公倍数
计算两个数的最大公约数(GCD)和最小公倍数(LCM)是基础算法题:
辗转相除法(欧几里得算法):
c复制int a, b, r, product;
scanf("%d %d", &a, &b);
product = a * b; // 保存原始乘积
// 确保a >= b
if (a < b) {
int temp = a;
a = b;
b = temp;
}
// 辗转相除核心算法
while (b != 0) {
r = a % b;
a = b;
b = r;
}
printf("最大公约数:%d\n", a);
printf("最小公倍数:%d\n", product / a);
算法优势:
- 时间复杂度O(log min(a,b))
- 无需暴力枚举,效率极高
- 是许多高级算法的基础
3.2 完数判断与水仙花数
完数(Perfect number)是指等于其真因子之和的数,如6=1+2+3:
c复制int num, sum = 0;
scanf("%d", &num);
for (int i = 1; i < num; i++) {
if (num % i == 0)
sum += i;
}
if (sum == num)
printf("%d是完数!\n", num);
else
printf("%d不是完数!\n", num);
水仙花数(Narcissistic number)是指n位数等于其各位数字n次方之和:
c复制for (int num = 100; num < 1000; num++) {
int a = num / 100; // 百位
int b = num / 10 % 10; // 十位
int c = num % 10; // 个位
if (num == a*a*a + b*b*b + c*c*c)
printf("%d是水仙花数\n", num);
}
扩展应用:
- 四叶玫瑰数(4位数)
- 五角星数(5位数)
- 阿姆斯特朗数的变种
4. 循环控制与输入处理
4.1 动态输入处理技术
实际开发中,经常需要处理不确定数量的输入,直到满足特定条件:
示例:输入若干成绩直到-1结束:
c复制int score, count = 0, sum = 0;
float average;
printf("输入成绩(-1结束):");
scanf("%d", &score);
while (score != -1) {
sum += score;
count++;
scanf("%d", &score); // 继续读取下一个成绩
}
if (count > 0) {
average = (float)sum / count;
printf("平均分:%.2f\n", average);
} else {
printf("未输入有效成绩\n");
}
关键技巧:
- 使用哨兵值(如-1)控制循环结束
- 避免除零错误(检查count>0)
- 类型转换保证精度(float)sum/count
4.2 字符统计与转换
通过循环处理字符流是文本处理的常见需求:
统计各类字符数量:
c复制char ch;
int letters = 0, digits = 0, others = 0;
printf("输入字符串:");
while ((ch = getchar()) != '\n') {
if (isalpha(ch)) letters++;
else if (isdigit(ch)) digits++;
else others++;
}
printf("字母:%d,数字:%d,其他:%d\n", letters, digits, others);
大小写转换:
c复制char ch;
while ((ch = getchar()) != '\n') {
if (ch >= 'a' && ch <= 'z')
ch -= 32; // 小写转大写
putchar(ch);
}
注意事项:
- 使用ctype.h中的isalpha()、isdigit()等函数更可靠
- ASCII码中,大小写字母相差32
- 考虑本地化字符集问题
5. 循环图形输出与游戏开发
5.1 基础图形输出模式
通过嵌套循环可以输出各种图形,这是理解循环控制的绝佳练习:
直角三角形:
c复制int rows;
scanf("%d", &rows);
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= i; j++) {
putchar('*');
}
putchar('\n');
}
镜像直角三角形:
c复制for (int i = 1; i <= rows; i++) {
// 输出空格
for (int j = 1; j <= rows - i; j++) {
putchar(' ');
}
// 输出星号
for (int j = 1; j <= i; j++) {
putchar('*');
}
putchar('\n');
}
设计原则:
- 外层循环控制行数
- 内层循环控制每行的内容
- 通过调整循环条件实现不同图形
5.2 猜数字游戏实现
综合运用循环和随机数生成实现简单游戏:
c复制#include <stdlib.h>
#include <time.h>
int main() {
srand(time(NULL)); // 初始化随机种子
int secret = rand() % 100 + 1; // 1-100的随机数
int guess, attempts = 0;
do {
printf("猜数字(1-100):");
scanf("%d", &guess);
attempts++;
if (guess > secret)
printf("太大了!\n");
else if (guess < secret)
printf("太小了!\n");
else
printf("恭喜!用了%d次猜中\n", attempts);
} while (guess != secret);
return 0;
}
增强功能建议:
- 添加尝试次数限制
- 记录最佳成绩
- 增加难度选择
- 添加输入验证
6. 高级循环模式与性能优化
6.1 斐波那契数列实现
斐波那契数列(Fibonacci sequence)是理解递推关系的经典案例:
迭代实现:
c复制int n = 20; // 计算前20项
long long a = 1, b = 1, c;
printf("%lld %lld ", a, b);
for (int i = 3; i <= n; i++) {
c = a + b;
printf("%lld ", c);
a = b;
b = c;
}
性能考虑:
- 使用迭代而非递归避免重复计算
- 使用long long防止快速溢出
- 时间复杂度O(n),空间复杂度O(1)
6.2 数列求和与数学分析
计算特殊数列的前n项和,如2/1+3/2+5/3+8/5+...:
c复制double sum = 0;
double a = 2, b = 1, temp;
for (int i = 1; i <= 10; i++) {
sum += a / b;
temp = a;
a = a + b;
b = temp;
}
printf("数列前10项和:%.6f\n", sum);
数学洞察:
- 这是斐波那契数列的分数形式
- 收敛于黄金比例(1+√5)/2 ≈ 1.618033988749895
- 可用于理解数值计算的精度问题
6.3 循环优化技巧
循环展开(Loop Unrolling):
c复制// 传统循环
for (int i = 0; i < 100; i++) {
process(i);
}
// 展开4次
for (int i = 0; i < 100; i += 4) {
process(i);
process(i+1);
process(i+2);
process(i+3);
}
优化原则:
- 减少循环控制开销
- 提高指令级并行
- 注意不要过度展开导致代码膨胀
避免重复计算:
c复制// 低效写法
for (int i = 0; i < strlen(s); i++) {...}
// 优化写法
int len = strlen(s);
for (int i = 0; i < len; i++) {...}
7. 常见问题与调试技巧
7.1 循环中的典型错误
-
死循环:
c复制int i = 0; while (i < 10) { printf("%d", i); // 忘记i++ } -
边界错误:
c复制// 错误:漏掉了最后一个元素 for (int i = 0; i < length - 1; i++) // 正确 for (int i = 0; i < length; i++) -
浮点数比较:
c复制// 错误:浮点数精确比较 while (x != 1.0) // 正确:使用容差比较 while (fabs(x - 1.0) > 1e-6)
7.2 调试方法与工具
-
printf调试法:
c复制while (condition) { printf("调试信息:i=%d, sum=%d\n", i, sum); // ... } -
使用调试器:
- gdb (Linux)
- Visual Studio Debugger (Windows)
- LLDB (macOS)
-
静态分析工具:
- cppcheck
- Clang Static Analyzer
- Coverity
7.3 性能分析与优化
时间测量:
c复制#include <time.h>
clock_t start = clock();
// 要测试的循环代码
clock_t end = clock();
double time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
printf("耗时:%f秒\n", time_used);
优化策略:
- 减少循环内部的计算量
- 避免在循环中调用耗时函数
- 考虑算法复杂度优化
- 利用缓存局部性原理
8. 工程实践建议
8.1 代码风格与可读性
-
一致的缩进和括号风格:
c复制// K&R风格 while (condition) { // ... } // 避免这种风格 while (condition) { // ... } -
有意义的变量名:
c复制// 差 int a, b, c; // 好 int student_count, total_score, average_grade; -
适当的注释:
c复制// 计算斐波那契数列前n项 // 使用迭代法避免递归的性能问题 long long fib(int n) { // ... }
8.2 防御性编程
-
输入验证:
c复制int n; while (1) { printf("输入正整数:"); if (scanf("%d", &n) == 1 && n > 0) break; // 清除错误输入 while (getchar() != '\n'); } -
边界检查:
c复制// 数组访问前检查索引 if (index >= 0 && index < array_size) { value = array[index]; } -
错误处理:
c复制FILE *fp = fopen("data.txt", "r"); if (fp == NULL) { perror("无法打开文件"); return EXIT_FAILURE; }
8.3 测试策略
-
单元测试:
- 测试边界条件(如空输入、最大值等)
- 测试典型用例和特殊用例
- 使用assert进行验证
-
测试用例设计:
c复制void test_factorial() { assert(factorial(0) == 1); assert(factorial(1) == 1); assert(factorial(5) == 120); // 测试溢出情况 } -
自动化测试:
- 使用测试框架如Unity、Check
- 集成到构建系统中
- 持续集成(CI)环境运行
9. 从循环到高级数据结构
9.1 数组处理模式
循环是处理数组的基础:
遍历数组:
c复制int arr[10] = {...};
for (int i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
查找元素:
c复制int search(int arr[], int size, int target) {
for (int i = 0; i < size; i++) {
if (arr[i] == target)
return i;
}
return -1;
}
9.2 字符串处理技术
C风格字符串本质是字符数组:
字符串长度:
c复制int strlen(const char *s) {
int len = 0;
while (*s++) len++;
return len;
}
字符串复制:
c复制void strcpy(char *dest, const char *src) {
while ((*dest++ = *src++));
}
9.3 多维数组与嵌套循环
处理矩阵等二维结构:
矩阵转置:
c复制#define N 3
int matrix[N][N] = {...};
int transpose[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
transpose[j][i] = matrix[i][j];
}
}
性能提示:
- 按行优先访问(C语言数组存储方式)
- 考虑缓存命中率
- 循环顺序影响性能
10. 现代C语言循环特性
10.1 C99增强特性
-
循环内声明变量:
c复制for (int i = 0; i < n; i++) { // C99允许 // ... } -
布尔类型:
c复制#include <stdbool.h> bool found = false; while (!found) { // ... }
10.2 基于范围的循环
C++风格的基于范围循环在C中模拟:
c复制int arr[] = {1, 2, 3, 4, 5};
int *begin = arr;
int *end = arr + sizeof(arr)/sizeof(arr[0]);
while (begin != end) {
printf("%d ", *begin);
begin++;
}
10.3 并行循环优化
利用OpenMP实现循环并行化:
c复制#include <omp.h>
#pragma omp parallel for
for (int i = 0; i < n; i++) {
// 可并行执行的代码
}
注意事项:
- 避免循环迭代间的依赖
- 注意共享变量的同步
- 考虑负载均衡
11. 实战项目建议
11.1 小型计算器
综合运用循环和条件判断:
c复制while (1) {
printf("\n选择操作:\n");
printf("1. 加法\n2. 减法\n...\n0. 退出\n");
int choice;
scanf("%d", &choice);
if (choice == 0) break;
double a, b;
printf("输入两个操作数:");
scanf("%lf %lf", &a, &b);
switch (choice) {
case 1: printf("结果:%.2lf", a + b); break;
// 其他操作...
default: printf("无效选择");
}
}
11.2 素数筛选器
使用埃拉托斯特尼筛法:
c复制#define MAX 1000
char is_prime[MAX] = {0};
// 初始化标记数组
for (int i = 2; i < MAX; i++) {
is_prime[i] = 1;
}
// 筛法核心
for (int i = 2; i * i < MAX; i++) {
if (is_prime[i]) {
for (int j = i * i; j < MAX; j += i) {
is_prime[j] = 0;
}
}
}
// 输出素数
for (int i = 2; i < MAX; i++) {
if (is_prime[i])
printf("%d ", i);
}
11.3 简单游戏开发
猜单词游戏:
c复制char word[] = "programming";
char guessed[20] = {0};
int attempts = 0, correct = 0;
while (correct < strlen(word)) {
printf("\n当前进度:");
for (int i = 0; i < strlen(word); i++) {
printf("%c ", guessed[i] ? guessed[i] : '_');
}
char guess;
printf("\n猜一个字母:");
scanf(" %c", &guess); // 注意空格跳过空白符
int found = 0;
for (int i = 0; i < strlen(word); i++) {
if (word[i] == guess && !guessed[i]) {
guessed[i] = guess;
correct++;
found = 1;
}
}
if (!found) {
attempts++;
printf("错误!剩余尝试:%d\n", 6 - attempts);
}
if (attempts >= 6) {
printf("游戏结束!单词是:%s\n", word);
break;
}
}
if (correct == strlen(word))
printf("恭喜获胜!用了%d次尝试\n", attempts);
12. 性能对比与算法选择
12.1 循环实现差异
计算π的三种方法对比:
-
莱布尼茨级数:
c复制double pi = 0, sign = 1; for (int i = 1; i < 1e6; i += 2) { pi += sign * 4 / i; sign = -sign; } -
巴塞尔问题:
c复制double sum = 0; for (int i = 1; i < 1e6; i++) { sum += 1.0 / (i * i); } double pi = sqrt(6 * sum); -
沃利斯公式:
c复制double pi = 2, term; for (int i = 1; i < 1e6; i++) { term = 4.0 * i * i / (4 * i * i - 1); pi *= term; }
收敛速度比较:
- 莱布尼茨:慢,需50万项达5位精度
- 巴塞尔:中等,需1万项达5位精度
- 沃利斯:快,需1000项达5位精度
12.2 时间复杂度分析
常见循环结构的时间复杂度:
-
单层循环:
c复制for (int i = 0; i < n; i++) // O(n) -
嵌套循环:
c复制for (int i = 0; i < n; i++) // O(n^2) for (int j = 0; j < n; j++) -
对数循环:
c复制for (int i = 1; i < n; i *= 2) // O(log n) -
多层不同循环:
c复制for (int i = 0; i < n; i++) // O(n + m) for (int j = 0; j < m; j++)
优化原则:
- 尽量减少嵌套循环层数
- 将高复杂度操作移出内层循环
- 考虑空间换时间策略
13. 跨平台开发注意事项
13.1 数据类型差异
不同平台基础类型可能不同:
| 类型 | 32位系统 | 64位系统 |
|---|---|---|
| int | 4字节 | 4字节 |
| long | 4字节 | 8字节 |
| long long | 8字节 | 8字节 |
| size_t | 4字节 | 8字节 |
最佳实践:
-
使用stdint.h中的明确类型:
c复制#include <stdint.h> int32_t i; // 明确32位有符号整数 uint64_t u; // 明确64位无符号整数 -
循环计数器使用size_t处理大数组:
c复制size_t i; for (i = 0; i < huge_number; i++)
13.2 输入输出差异
不同平台换行符可能不同:
- Windows: \r\n
- Unix/Linux: \n
- Mac OS(旧): \r
可移植处理:
c复制// 使用标准库自动处理
printf("跨平台文本\n");
fputs("安全输出", stdout);
13.3 编译器特定优化
利用编译器指令优化循环:
c复制// GCC的likely/unlikely提示
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
for (int i = 0; i < n; i++) {
if (likely(i % 2 == 0)) {
// 大概率路径
} else {
// 小概率路径
}
}
跨平台方案:
c复制#ifdef __GNUC__
#define LIKELY(x) __builtin_expect(!!(x), 1)
#else
#define LIKELY(x) (x)
#endif
14. 安全编程实践
14.1 缓冲区溢出防护
循环处理数组时务必检查边界:
c复制// 危险代码
char buf[10];
for (int i = 0; i < user_input_len; i++) {
buf[i] = user_input[i]; // 可能溢出
}
// 安全代码
char buf[10];
int copy_len = user_input_len < 10 ? user_input_len : 9;
for (int i = 0; i < copy_len; i++) {
buf[i] = user_input[i];
}
buf[copy_len] = '\0'; // 确保字符串终止
14.2 整数溢出防护
循环计数器可能溢出:
c复制// 危险代码
for (unsigned int i = n; i >= 0; i--) // 无限循环
// 安全代码
for (unsigned int i = n; i > 0; ) {
i--; // 先减后处理
// ...
}
14.3 输入验证
所有外部输入都应验证:
c复制int n;
while (1) {
printf("输入数组大小(1-1000):");
if (scanf("%d", &n) == 1 && n >= 1 && n <= 1000)
break;
// 清除错误输入
while (getchar() != '\n');
printf("无效输入!\n");
}
int *arr = malloc(n * sizeof(int));
if (arr == NULL) {
fprintf(stderr, "内存分配失败\n");
exit(EXIT_FAILURE);
}
15. 调试与性能分析工具
15.1 GDB调试技巧
基本调试流程:
- 编译时添加-g选项:
gcc -g program.c - 启动gdb:
gdb ./a.out - 常用命令:
break 行号/函数名设置断点run启动程序next单步执行print 变量查看变量值watch 变量监视变量变化backtrace查看调用栈
循环调试示例:
c复制for (int i = 0; i < 10; i++) {
printf("%d\n", i*i); // 在此行设置断点
}
15.2 Valgrind内存检查
检测内存泄漏和越界访问:
bash复制valgrind --leak-check=full ./program
典型输出分析:
code复制==12345== Invalid write of size 4
==12345== at 0x123456: main (program.c:10)
==12345== Address 0x123456 is 0 bytes after a block of size 10 alloc'd
15.3 性能分析工具
gprof使用:
- 编译时添加-pg:
gcc -pg program.c - 运行程序生成gmon.out
- 分析结果:
gprof ./a.out
perf工具:
bash复制perf stat ./program # 基本统计
perf record ./program # 详细分析
perf report # 查看报告
16. 代码重构与质量提升
16.1 函数提取
将复杂循环逻辑提取为函数:
c复制// 重构前
for (int i = 0; i < n; i++) {
// 复杂逻辑...
}
// 重构后
void process_element(int index) {
// 复杂逻辑...
}
for (int i = 0; i < n; i++) {
process_element(i);
}
优点:
- 提高代码可读性
- 便于单元测试
- 减少重复代码
16.2 循环不变式外提
将循环内不变的计算移到外部:
c复制// 优化前
for (int i = 0; i < n; i++) {
result += data[i] * (M_PI / 180.0);
}
// 优化后
const double radian = M_PI / 180.0;
for (int i = 0; i < n; i++) {
result += data[i] * radian;
}
16.3 循环展开策略
手动或编译器指导的循环展开:
c复制// 手动展开
for (int i = 0; i < n; i += 4) {
process(i);
process(i+1);
process(i+2);
process(i+3);
}
// 处理剩余元素
for (; i < n; i++) {
process(i);
}
编译器指令:
c复制#pragma GCC unroll 4
for (int i = 0; i < n; i++) {
// ...
}
17. 现代C标准新特性
17.1 C11泛型选择
使用_Generic处理不同类型:
c复制#define print_type(x) _Generic((x), \
int: printf("%d\n", x), \
double: printf("%f\n", x), \
default: printf("%p\n", (void*)x) \
)
int main() {
int i = 10;
double d = 3.14;
print_type(i); // 输出: 10
print_type(d); // 输出: 3.140000
}
17.2 静态断言
编译时检查循环相关常量:
c复制#define MAX_SIZE 100
_Static_assert(MAX_SIZE > 0, "MAX_SIZE必须为正数");
for (int i = 0; i < MAX_SIZE; i++) {
// ...
}
17.3 对齐内存访问
优化循环内存访问:
c复制#include <stdalign.h>
alignas(16) double data[1000]; // 16字节对齐
for (int i = 0; i < 1000; i++) {
// 对齐访问可能更快
data[i] = i * 0.1;
}
18. 多线程与并发循环
18.1 POSIX线程基础
使用pthread实现并行循环:
c复制#include <pthread.h>
#define THREADS 4
#define N 1000
struct ThreadData {
int start;
int end;
double *array;
};
void *worker(void *arg) {
struct ThreadData *data = arg;
for (int i = data->start; i < data->end; i++) {
data->array[i] = i * 0.1;
}
return NULL;
}
int main() {