2011-07-24 65 views
1
#include <stdio.h> 
#include <stdlib.h> 

const int * func() 
{ 
    int * i = malloc(sizeof(int)); 
    (*i) = 5; // initialize the value of the memory area 
    return i; 
} 

int main() 
{ 
    int * p = func(); 
    printf("%d\n", (*p)); 
    (*p) = 3;  // attempt to change the memory area - compiles fine 
    printf("%d\n", (*p)); 
    free(p); 
    return 0; 
} 

,爲什麼編譯器還允許我修改,即使(*p)func()返回一個const指針?的C函數返回常量指針分配給非const指針 - 警告不是錯誤

我正在使用gcc,它只在int * p = func();行顯示警告:「警告:初始化放棄指針目標類型的限定符」。

謝謝。

+0

有一種方法讓編譯器顯示錯誤,而不是此警告? – printfede

+0

@prinfede:'-pedantic-errors'或'-Werror'。 –

+0

OP返回的內容不是一個常量指針,而是一個指向const(或只讀)對象的指針。 –

回答

4

您的程序無效。 C禁止像這樣隱含地移除const,並且符合規範GCC應該至少給你提供該代碼的警告。您需要演員才能刪除const

消耗了一個警告,但是你可以依靠程序來工作(儘管從標準的角度來看不再),因爲指針指向一個malloc的內存區域。你可以寫信給那個地區。指向某些內存的const T*並不意味着此後內存被標記爲不可變。

請注意,標準不需要編譯器來拒絕任何程序。標準只需要編譯器有時向用戶發送消息。無論是錯誤信息還是警告信號,以及信號如何發射以及發射後發生的任何事情,標準都沒有明確規定。

1

您正在將const指針轉換爲普通指針,這實際上允許您更改指針。你打破了你通過返回一個常量指針所做的「契約」,但由於C是一種弱類型語言,它在語法上是合法的。

基本上GCC幫你在這裏。從句法上來說,將const指針轉換爲常規指針是合法的,但是您可能不希望這樣做,因此GCC會引發警告。

閱讀design by contract

0

首先,內存在main中是有效的,因爲它存儲在堆中並且沒有被銷燬/釋放。所以編譯器只是向你發出警告。

如果您嘗試

const int * p = func(); 

那麼當然(*p) = 3會報錯。

2

編譯器和C語言「允許」你做所有愚蠢的事情,特別是如果你忽略警告。 const int*int*的轉換是編譯器可以檢測到此處存在任何錯誤的唯一點,並且它發出了該轉換的警告。這與你所得到的一樣不滿,這也是你不應該忽視警告的原因。

由於此程序的行爲已被定義(由GCC定義,如果您明確地將其轉換爲const int*),至少可能您所做的事情確實是您打算執行的操作。這就是代碼被接受的原因。

相關問題