【问题标题】:Why are these dynamically allocated arrays different?为什么这些动态分配的数组不同?
【发布时间】:2021-03-02 12:05:27
【问题描述】:

我有两个数组。它们应该从相同的东西开始,然后我会改变一个,并在一些计算中使用它们。但是(!)它们的开始并不相同。这基本上就是我想要做的(我认为):

int main() {

    int* arr1 = (int *) malloc( sizeof(int) * 7 );

    int* arr2 = (int *) malloc( sizeof(int) * 7 );

    for (int i=1; i<7; i++) {
        *(arr1 + ( sizeof(int) * i )) = i;
        *(arr2 + ( sizeof(int) * i )) = i;
    }

    // print the arrays

    // they should be the same, but...

    // arr1 is { 1, 2, 3, 4, 5, 6, 7 }

    // arr2 is { 4, 5, 6, 7, 5, 6, 7 }

}

我已经打印了数组,因为它们正在构建,并且存在我无法解释的行为(但假设与动态分配的数组放在堆上而不是堆栈上的事实有关,尽管我没有'不知道这是什么意思)。

arr1 是这样构建的,即使最终证明是正确的:

1: {1,2,0,0,0,0,0}

2: {1,2,0,1,2,0,0}

3: {1,2,3,1,2,3,0}

4: {1,2,3,1,2,3,0}

5: {1,2,3,4,2,3,4}

6: {1,2,3,4,5,3,4}

7: {1,2,3,4,5,6,4}

8: {1,2,3,4,5,6,7}

和arr2这样(问题一):

1: {1,2,0,0,0,0,0}

2: {1,2,3,0,0,0,0}

3: {4,2,3,4,0,0,0}

4: {4,5,3,4,5,0,0}

5: {4,5,6,4,5,6,0}

6: {4,5,6,7,5,6,7}

在我看来,当我到达第 4 个元素时,它开始在每次迭代中修改两个元素。

同理。对于理解这一点的任何帮助将不胜感激。

这是我的完整代码(我知道这很糟糕)。排名和排名1是有问题的数组:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>



int main(){
    // Declare array of topics

    // need to remove these [] by using malloc again, and then hard coding each element
    char* topics[7] = {
        "Marine Conservation", "Climate Change", "Large-Scale Conflict/War",
        "Government Accountability", "COVID-19", "Curing Cancer", "Unemployment"
    };

    // declare other variables

    int rate, totalRating, i, j, respondents=0;

    double avg;

    // Declare array of responses

    //int responses[7][10];
    int* responses = malloc(sizeof(int)*70);
    int input_counter = 0;
    int user_input = 1;
    do {
        
        //printf("Person %d:\n", (i+1));
        printf("Please rate each topic from 1-10:\n");
        for(int i=0; i<7; i++){
            printf("%s: ", *(topics+(i*sizeof(char))));
            int rate;
            while(1){
                scanf(" %d", &rate);
                if(rate<0 || rate>10){
                    printf("Your rating must be between 1-10. Please try again:");
                    continue;
                }
                else break;
            }
            *(responses+(input_counter*sizeof(int))+(i*sizeof(int))) = rate;
        } 
        input_counter++;
        printf("Would you like to input response from another person?  1 for yes, 0 for no.");
        scanf(" %d", &user_input);
    } while(input_counter < 10 && user_input != 0);
    printf("here yo");
    int* rankings = (int *) malloc(sizeof(int)*7);
    int* rankings1 = (int *) malloc(sizeof(int)*7);
    printf("\nsize of int is: %d\n",sizeof(int));
    printf("%d is 28 away from %d", rankings,rankings1);

    // Print the array along with the average rating for each topic
    int highest_rated = 0, lowest_rated = 0;
    int highest_rated_points = 0;
    int lowest_rated_points = 11;
    //int* sorted_topics = (int *) malloc(sizeof(int)*7);
    for(i=0; i<7; i++){
        
        int cat_respond = 0;
        totalRating = 0;


        printf("%-20s: ", *(topics+(i*sizeof(char))));
        for(j=0; j<input_counter; j++){
            //printf("total rating is:%d  ",*(responses+(sizeof(int)*i)+(sizeof(int)*j)));
            totalRating += *(responses+(sizeof(int)*i)+(sizeof(int)*j));
            printf("%d \t",*(responses+(sizeof(int)*i)+(sizeof(int)*j)));
            cat_respond++;
        }
        // do highest/lowest rated calc
        if (highest_rated_points < totalRating) {
            highest_rated_points = totalRating;
            highest_rated = i;
        } 
        if (lowest_rated_points > totalRating) {
            lowest_rated_points = totalRating;
            lowest_rated = i;
        }
        printf("TotalRating %d at i is: %d", totalRating, i);
        //*(sorted_topics+(sizeof(int)*i)) = totalRating;
        *(rankings+(sizeof(int)*i)) = totalRating;
        *(rankings1+(sizeof(int)*i)) = totalRating;
        printf("the new element is: %d",*(rankings1+(sizeof(int)*i)));
        // do avg calc
        float avg = totalRating/cat_respond;
        printf("Avg: %.2f\n",avg);
        printf("arr is now: \n");
        for(int k=0;k<7; k++){
            printf("k is : %d thing is : %d",k, (sizeof(int)*k));
            printf("here is: %d\n", *(rankings1 + (sizeof(int)*k) ) );
         }
        
    }

    // display highest/lowest
    printf("The highest rated issue was: %s with a total rating of: %d\n", *(topics+(sizeof(char)*highest_rated)), highest_rated_points);
    printf("The lowest rated issue was: %s with a total rating of: %d\n", *(topics+(sizeof(char)*lowest_rated)), lowest_rated_points);

    // do sorting  - adapted from https://www.sanfoundry.com/c-program-sort-array-descending-order/
    printf("starting arry is :\n");
    for(int i=0; i<7; i++){
        printf("i is : %d",i);
        printf("here is: %d\n", *(rankings1+(sizeof(int)*i)));
    }
    for (int i = 0; i < 7; i++) 
    {
        for (int j = i + 1; j < 7; j++) 
        {
            if (*(rankings1+(sizeof(int)*i)) < *(rankings1+(sizeof(int)*j))) 
            {
                int a = *(rankings1+(sizeof(int)*i));
                *(rankings1+(sizeof(int)*i)) = *(rankings1+(sizeof(int)*j));
                *(rankings1+(sizeof(int)*j)) = a;
                printf("made swaping, array is now:\n");
                for(int i=0; i<7; i++){
                    printf("i is : %d",i);
                    printf("here is: %d\n", *(rankings1+(sizeof(int)*i)));
                }
            }
        }
    }
    for(int i=0; i<7; i++){
        printf("i is : %d",i);
        printf("here is: %d\n", *(rankings1+(sizeof(int)*i)));
    }
    
    printf("The issues ranked from highest to lowest are:\n");
    int curr_max;
    for (int i=0; i<7; i++) {
        int topic_num = 0;
        curr_max = *(rankings1+(sizeof(int)*i));
        for (int j=0; j<7; j++) {
            if (*(rankings+(sizeof(int)*j)) == curr_max) {
                topic_num = j;
                // *del* the element
                *(rankings+(sizeof(int)*j)) = -1;
                break;
            }
        }
        printf("%d: %s with a total rating of %d\n",i+1,*(topics+(sizeof(char) * topic_num)),curr_max); 
    }


    // total respondents calc
    for (int i=0; i<10; i++) {
        if (*(responses+(sizeof(int)*i)) != 0) 
            respondents++;
    }
    printf("Total respondents: %d\n", respondents);

    free(responses);
    free(rankings);
    free(rankings1);
}

【问题讨论】:

  • *(arr1 + ( sizeof(int) * i )) = i; arr 是一个int*,所以每添加一个 1 到指针上,地址就会移动一个 int 的大小。 sizeof(int) 不是必需的,它正在将位置移动到有效数组元素范围之外。
  • arr1 + ( sizeof(int) * i ) 是错误的。应该是arr1 + i。因为那个表达式是指针算术。使用指针算法,编译器将生成正确的“步骤”。
  • 使用下标——它们更容易正确(arr1[i] = i;)。不要在*(arr1 + ( sizeof(int) * i )) = i; 中乘以sizeof(int) — 编译器也会为您执行此操作,因此您访问的数组越界。在 C 中,数组从索引 0 开始,而不是索引 1。使用 for (int i = 0; i &lt; 7; i++) 进行循环。
  • 我不能根据要求使用下标。不过,你们所有人都是对的,只需要删除几乎所有的 sizeofs。非常感谢!
  • @Faulk sizeofs 不是唯一的问题。即使没有它们,您也会溢出缓冲区,因为索引 7 超出了范围。

标签: arrays c pointers dynamic-memory-allocation


【解决方案1】:

您观察到您所做的行为是因为程序的行为未定义。 7 个int 对象的数组中的最后一个有效索引是 6。但是您一直写入索引 sizeof(int) * 7,假设 4 字节 int 是 28。28 大于 6,所以它超出了界限缓冲区。

附:使用下标运算符使代码可读。以下是使用序列 1、2、3、... 分配数组元素的正确方法:

int count = 7;
int* arr1 = malloc(sizeof(int) * count;
int* arr2 = malloc(sizeof(int) * count);
for (int i=0; i<count; i++) {
    arr1[i] = i + 1;
    arr2[i] = i + 1;
}

【讨论】:

    猜你喜欢
    • 2014-09-14
    • 1970-01-01
    • 1970-01-01
    • 2017-06-03
    • 2013-03-17
    • 2012-02-18
    • 1970-01-01
    • 2013-03-21
    • 2018-01-26
    相关资源
    最近更新 更多