簡體   English   中英

數組內的值錯誤

[英]Wrong values inside of array

我是一名新的C語言學習者,面臨2個問題。 (寫在同一頁上,因為我認為這是兩者的根本原因)

int mrr [2][3];

for (int r=0;r<2;r++)
{
    for (int c=0; c<3; c++)
        printf("[%d],[%d]:%d\n",r,c,mrr[r][c]);
}

我讀到,如果我們不為新創建的數組提供值,則它在其所有單元格內的默認值為0。 但是當我打印結果時,它顯示:

[0],[0]:0
[0],[1]:4201072
[0],[2]:6422224
[1],[0]:6422280
[1],[1]:6422476
[1],[2]:1977208000

其次,以下代碼返回完全意外的值(平均值)431374336.000000

double getAverage(int arr[], int size) {

   int i;
   double avg;
   double sum = 0;

   for (i = 0; i < size; ++i) {
      sum += arr[i];
   }
   avg = sum / size;

   return avg;
}

double balance[5] = {1000, 2, 7, 17, 50};
double avg = getAverage(balance, 5 );
printf( "Average value is: %f ", avg );

在函數內部定義的,沒有static_Thread_local對象不會自動初始化,並且具有不確定的值。 為了確保初始化數組mrr ,請使用int mrr[2][3] = { 0 };定義它int mrr[2][3] = { 0 }; ,它將初始化為全零。

第二個問題中的代碼不完整,但是,大概是在調用函數中定義了數組,並且未初始化,因此其值是不確定的。

默認情況下,在函數內部定義的數組(即本地數組)的[值]是不確定的。 另一方面,全局(即靜態)變量默認情況下初始化為0。 參見相關文章: C中int數組的初始值

要解決您的問題,只需手動初始化數組即可,例如

for (int r=0;r<2;r++)
{
    for (int c=0; c<3; c++) {
        mrr[r][c] = 0;
        printf("[%d],[%d]:%d\n",r,c,mrr[r][c]);
    }
}

您對未初始化變量的問題已被注釋和其他答案很好地涵蓋了。 這個答案是您的第二個問題,關於getAverage()的意外輸出。

您將balance定義為double數組,但是getAverage()期望使用int數組。 當我改變時:

double getAverage(int arr[], int size) { ... }

至:

double getAverage(double arr[], int size) { ... }

我得到了預期的結果:215.2。 原始代碼中的隱式類型轉換[1]導致意外行為。

另外,我不知道您使用的是什么編譯器,但是當我編譯原始代碼[2]時, gcc發出了以下警告:

warning: incompatible pointer types passing 'double [5]' to parameter of type 'int *'

...這是麻煩正在醞釀中的死胡同。 如果您的編譯器沒有生成此警告,或者您取消了警告,或者如果警告已記錄到文件或您未查看的內容中,則建議再次使它們可見。 注意編譯器警告為我節省了無盡的痛苦。

[1]“類型轉換”可能不是此處的最佳術語; 即使存在一些陷阱,類型轉換通常也是良性的; 這里發生的是,將組成double值的字節讀為int ,並且這兩種數據類型的字節結構非常不同; 這就是為什么原始代碼的輸出看起來好像在處理如此瘋狂的數字:例如,當作為int讀取時,用於將“ 17”表示為雙精度字符的字節變得非常不同。 更糟糕的是,逐步遍歷組成double值數組的字節,就好像它是一個int值數組一樣,它甚至可能根本不在適當的元素邊界處查看該數組元素。 簡而言之,類型差異會造成嚴重破壞。

[2]“原始代碼”是指您的代碼具有足夠的開銷代碼來進行編譯,例如include pragma和main()主體; 我總體上同意關於提供完整的最小示例的其他評論。

這個補充性回答是針對OP對我先前的回答的評論。 防御者問:

“我還有一些問題。如果期望一個int類型的數組,並且我發送了為什么會在360度范圍內更改結果的信息,我發送了兩次。我仍然沒有得到答案。”

short intint之間的類型沖突更容易說明這一點,但是相同的想法適用於intdouble

看一下這段代碼:

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

void functionA(short int[], int size);

int main(void) {

    printf("sizeof short int : %lu\n", sizeof(short int));
    printf("sizeof int       : %lu\n", sizeof(int));
    printf("\n\n");

    printf("====  sending short int to functionA() ====\n");
    short int shortdata[4] = {10, 20, 50, 100};
    functionA(shortdata, 4);

    printf("====  sending int to functionA() ====\n");
    int intdata[4] = {10, 20, 50, 100};
    functionA(intdata, 4);
}

void functionA(short int arr[], int size) {

   int i;

   char* ptr;

   for (i = 0; i < size; ++i) {
      ptr = &arr[i];
      printf("bytes of 'arr[%d]' : %x %x\n", i, *ptr, *(ptr+1));

      printf("value of 'arr[%d]' : %d\n", i, arr[i]);

      printf("\n");
   }
}

產生以下輸出:

sizeof short int : 2
sizeof int       : 4


====  sending short int to functionA() ====
bytes of 'arr[0]' : a 0
value of 'arr[0]' : 10

bytes of 'arr[1]' : 14 0
value of 'arr[1]' : 20

bytes of 'arr[2]' : 32 0
value of 'arr[2]' : 50

bytes of 'arr[3]' : 64 0
value of 'arr[3]' : 100

====  sending int to functionA() ====
bytes of 'arr[0]' : a 0
value of 'arr[0]' : 10

bytes of 'arr[1]' : 0 0
value of 'arr[1]' : 0

bytes of 'arr[2]' : 14 0
value of 'arr[2]' : 20

bytes of 'arr[3]' : 0 0
value of 'arr[3]' : 0

輸出的前兩行表明,在我的機器上, short int占用2個字節的內存,而int占用4個字節。

functionA()期望一個short int數組,當我發送一個short int[] ,我們看到了期望的輸出。 組成數組第一個元素的字節為0x0a 0x00 ,十進制為“ 10”; 組成數組第二個元素的字節為0x14 0x00 ,十進制為“ 20”; 等等。

但是,當我向int[]發送functionA() ,每個元素發送4個字節,因此,當它遍歷數組時,不會正確看到元素。 它對第一個元素還可以,但這僅是因為它很小。 當它尋找第二個元素時,實際上是在尋找第一個元素的最后兩個字節,因此它看到0x00 0x00或“ 0”; 當它尋找第三個元素時,它正在尋找第二個元素的前兩個字節,並且看到0x14 0x00或“ 20”; 等等。

另一種顯示方式是shortdata的字節是這樣的:

0a 00 14 00 32 00 64 00

intdata的字節是這樣的:

0a 00 00 00 14 00 00 00 32 00 00 00 64 00 00 00

因為functionA()期望一個short int[] ,所以它intdata這種方式對待intdata -每個元素兩個字節-並視為其元素:

arr[0] : 0a 00
arr[1] : 00 00
arr[2] : 14 00
arr[3] : 00 00

這與您的代碼類似。 您的getAverage()期望的是int[] ,因此當您將其發送為double[] ,它不會按照您的預期方式看到字節。

intdouble之間的沖突比short intint之間的沖突更為激烈;這是因為除了大小不同(在大多數現代計算機上, int是4個字節, double是8個字節)之外,還存儲了浮點數作為指數和尾數-因此字節值的含義完全不同。)

希望以上說明對您有所幫助,並鼓勵您嘗試上面的代碼,並閱讀C內存的內部知識,因為它與分配和處理變量有關。 作為新的C程序員,您將深入了解可以繼續使用C進行編程的基礎知識。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM