C 为什么使用无关的printf语句会导致程序输出发生更改?

C 为什么使用无关的printf语句会导致程序输出发生更改?,c,printf,C,Printf,我被一个程序困住了,其中只有printf语句会导致输出发生变化 我有一个n元素数组。对于每个d连续元素的中值,如果(d+1)第个元素大于或等于其两倍(中值),我将增加通知的值。可以参考完整的问题陈述 这是我的节目: #include <math.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <assert.h> #include <li

我被一个程序困住了,其中只有
printf
语句会导致输出发生变化

我有一个
n
元素数组。对于每个
d
连续元素的
中值
,如果
(d+1)第个元素
大于或等于其两倍(中值),我将增加
通知
的值。可以参考完整的问题陈述

这是我的节目:

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>

#define RANGE 200

float find_median(int *freq, int *ar, int i, int d) {
    int *count = (int *)calloc(sizeof(int), RANGE + 1);
    for (int j = 0; j <= RANGE; j++) {
        count[j] = freq[j];
    }
    for (int j = 1; j <= RANGE; j++) {
        count[j] += count[j - 1];
    }
    int *arr = (int *)malloc(sizeof(int) * d);
    float median;
    for (int j = i; j < i + d; j++) {
        int index = count[ar[j]] - 1;
        arr[index] = ar[j];
        count[ar[j]]--;
        if (index == d / 2) {
            if (d % 2 == 0) {
                median = (float)(arr[index] + arr[index - 1]) / 2;
            } else {
                median = arr[index];
            }
            break;
        }
    }
    free(count);
    free(arr);
    return median;
}

int main() {
    int n, d;
    scanf("%d %d", &n, &d);
    int *arr = malloc(sizeof(int) * n);
    for (int i = 0; i < n; i++) {
        scanf("%i", &arr[i]);
    }
    int *freq = (int *)calloc(sizeof(int), RANGE + 1);
    int notifications = 0;
    if (d < n) {
        for (int i = 0; i < d; i++)
            freq[arr[i]]++;
        for (int i = 0; i < n - d; i++) {
            float median = find_median(freq, arr, i, d);   /* Count sorts the arr elements in the range i to i+d-1 and returns the median */
            if (arr[i + d] >= 2 * median) {      /* If the (i+d)th element is  greater or equals to twice the median, increments notifications*/
                printf("X");
                notifications++;
            }
            freq[arr[i]]--;
            freq[arr[i + d]]++;
        }
    }
    printf("%d", notifications);
    return 0;
}
#包括
#包括
#包括
#包括
#include,程序输出
936
作为
通知的值,而当我刚刚排除语句
printf(“X”)
时,程序输出
1027
作为
通知的值。

我真的无法理解是什么导致了我的程序中出现这种行为,以及我遗漏了什么/监督了什么。

您的程序在这里有未定义的行为:

for (int j = 0; j <= RANGE; j++) {
    count[j] += count[j - 1];
}

for(int j=0;j您的程序在这里有未定义的行为:

for (int j = 0; j <= RANGE; j++) {
    count[j] += count[j - 1];
}
for(int j=0;j您的程序(在某些情况下)有。您真的应该(而且您还不够害怕)

我真的无法理解是什么导致我的程序中出现这种行为

对于UB,这个问题是没有意义的。你需要深入了解实现细节(例如,研究程序生成的机器代码,以及C编译器和标准库的代码)以了解更多内容。你可能不想这样做(这可能需要数年的工作)

请尽快阅读Lattner在

我缺少/监督的东西

你对UB的理解还不够透彻。请注意,编程语言是一种规范(以及针对它的代码),而不是一种软件(例如,你的编译器)。程序很重要

正如我在评论中所说:

  • 使用所有警告和调试信息编译(
    gcc-Wall-Wextra-g
    with)

  • 改进您的代码以不获取警告;也许还可以尝试其他类似的编译器,并努力从中也不获取警告(因为不同的编译器给出不同的警告)

  • 考虑使用一些系统,比如保留代码的各种变体,以及一些工具

  • 多想想你的程序和它的内部

  • 使用调试器(
    gdb
    ),尤其是使用,以了解进程的内部状态;并且有几个案例可以在调试器下运行,也可以不使用调试器

  • 使用诸如的地址消毒剂
    -fsanize=address
    等工具和类似工具

  • 使用方法

  • 有时考虑工具(例如),它们需要使用专门知识,和/或给出许多假阳性。

  • 阅读更多关于编程(例如)和C编程语言的内容。下载并学习编程语言规范(其中提到UB时要非常小心)。请仔细阅读您正在使用的每个标准或外部函数的。还要研究编译器和其他工具的功能。处理错误和失败案例(例如,和可能失败)

调试是困难的(例如,由于,of,等…)-但有时是有趣和具有挑战性的。您可以花数周时间查找一个bug。如果不深入了解实现细节,您通常无法理解bug程序的行为(研究编译器生成的机器代码,研究编译器的代码)

另外,你的问题显示出一种错误的心态——你应该改进这种心态——以及对UB的误解。

你的程序(在某些情况下)确实应该这样做(而且你还不够害怕)

我真的无法理解是什么导致我的程序中出现这种行为

对于UB,这个问题是没有意义的。你需要深入了解实现细节(例如,研究程序生成的机器代码,以及C编译器和标准库的代码)以了解更多内容。你可能不想这样做(这可能需要数年的工作)

请尽快阅读Lattner在

我缺少/监督的东西

你对UB的理解还不够透彻。请注意,编程语言是一种规范(以及针对它的代码),而不是一种软件(例如,你的编译器)。程序很重要

正如我在评论中所说:

  • 使用所有警告和调试信息编译(
    gcc-Wall-Wextra-g
    with)

  • 改进您的代码以不获取警告;也许还可以尝试其他类似的编译器,并努力从中也不获取警告(因为不同的编译器给出不同的警告)

  • 考虑使用一些系统,比如保留代码的各种变体,以及一些工具

  • 多想想你的程序和它的内部

  • 使用调试器(
    gdb
    ),尤其是使用,以了解进程的内部状态;并且有几个案例可以在调试器下运行,也可以不使用调试器

  • 使用诸如的地址消毒剂
    -fsanize=address
    等工具和类似工具

  • 使用方法

  • 有时考虑工具(例如),它们需要使用专门知识,和/或给出许多假阳性。

  • 阅读更多关于编程(例如)和C编程语言的内容。下载并学习编程语言规范(其中提到UB时要非常小心)。请仔细阅读您正在使用的每个标准或外部函数的。还要研究编译器和其他工具的功能。处理错误和失败案例(例如,和可能失败)

调试是困难的(例如,由于、of等…)-但有时很有趣,也很有挑战性。你可以花数周时间查找一个bug。而且你通常无法理解bug程序的行为