簡體   English   中英

何時強制類型轉換指針?

[英]When is typecasting a pointer allowed?

我正在為考試而學習,下面給出的示例問題之一是:

“當分配給new_val時,以下哪個表達式(該表達式將替換HERE )將輸出7 選擇所有適用項:

float m = 7.0
int *a = (int *) &m;

int new_val = HERE;
printf("%d\n", new_val);

(a)*(int *)&m

(b)* a

(c)(整數)米

(d)以上都不是。


答案僅是(c)

我已經在自己的機器上運行了該程序,發現符合答案。 但是,我想知道有人怎么能找到這個答案? 更一般而言,我在理解有關強制轉換指針的規則時遇到了麻煩。 我已經閱讀了StackOverflow上的其他幾篇文章,對我來說並沒有太大幫助。

我想知道是否有人可以幫助澄清我如何解決與此類似的問題。

但是使用

int new_val = (int)m;

使用int* a = ...忽略在上一行中完成的所有操作

因此,您只是將原始浮點數m投射回一個int。

編輯嘗試以下操作:


#include "stdio.h"

int main(int argc, char** argv) {
    float m = 7.1;
    int new_val = (int)m;
    printf("%d\n", new_val);

}

解決此問題的方法是查看每個選擇答案,然后弄清該語句的含義。 考慮變量的類型。

但是,在這種情況下,將float *強制轉換為int *只是意味着您要告訴編譯器“您知道該存儲有float內存地址?像訪問int一樣訪問該內存”。 intfloat不會以相同的方式存儲在內存中,因此嘗試以錯誤的格式訪問它會產生無意義的結果。 強制轉換指針不會轉換指針指向的數據。

對於選項c,請注意,您沒有強制轉換指針,而是將float轉換為int 這是一個簡單的轉換。

這個問題是有缺陷的。 C標准允許(a),(b)和(c)中的每一個都打印“ 7”,並且還允許它們中的每一個都不打印“ 7”。

對於(a),我們有int new_val = * (int *) &m; 在這里, &m類型為float * ,因此將float *轉換為int * C 2018 6.3.2.3 7告訴我們我們可以進行這種轉換:“指向對象類型的指針可能會轉換為指向不同對象類型的指針。”但也“如果生成的指針未針對引用類型正確對齊,因此,在float的對齊要求比int嚴格的實現中,該行為不是由C標准定義的,因此,合格的C實現允許打印“ 7”,並且不允許打印“7”。 假設實現成功評估了轉換而沒有對齊問題,則應用* 下一節將對此進行介紹。

在(b)中,我們有int new_val = *a; ,其中a已初始化為(int *) &m; 與(a)一樣,此表達式將float *轉換為int * ,因此不符合上面的對齊問題。 但是,再次假設避免了對齊問題,它隨后使用指針訪問float對象m ,就好像它是一個int 這違反了C 2018 6.5 7,其中聲明“對象只能通過具有以下類型之一的左值表達式訪問其存儲的值:”然后繼續列出各種選項,這些選項均不允許以以下方式訪問float :一個int 由於違反了此“應有”要求,C 2018 4 1告訴我們該行為未定義:“如果違反了在約束或運行時約束之外出現的“應有”或“不應”要求,則該行為未定義。 ”由於C標准未定義行為,因此允許的符合性實現允許打印“ 7”,而不允許打印“ 7”。

在(c)中,我們有int new_val = (int) m; ,其中m是值為7的float 。這是定義明確的轉換,結果為7,因此printf("%d\\n", new_val); 通常會打印“ 7”(帶有換行符)。 但是,更早的問題仍然存在:即使使用new_val正確定義,更早的聲明int *a = (int *) &m; 執行可能導致未定義行為的轉換。 在我們閱讀new_val的定義之前,這可能導致未定義的行為。 因此,與(a)和(b)一樣,一致的實現方式允許打印“ 7”,而不允許打印“ 7”。

因為a = (int *)&m ,所以選項(a)和(b)相同。 在兩種情況下,您都使用m的地址,將其強制轉換為int * ,然后取消引用。

(a)和(b)不起作用的原因是&m是指向floatfloat * )的指針,而不是指向intint * )的指針。

考慮兩個指針,一個是指向Window的指針,另一個是指向Joystick的指針。 很明顯,您不能將它們混在一起,對嗎? 您不能將指向Window的指針傳遞給需要指向Joystick的指針的函數。 您可以投射指針,但這不會使Window變成Joystick

因此,指向float指針與指向int指針是不兼容的,並且如果將指針轉換為float並指向int的指針並嘗試對其進行取消引用,則將得到垃圾。

但是(c)之所以有效,是因為這里要獲取實際的floatm並要求編譯器將該值轉換為int值。 編譯器知道如何執行此操作並生成正確的代碼。

您可能想知道,如果編譯器知道如何將float轉換為int ,為什么不能將float的指針轉換為int的指針呢? 實際上確實如此; 那是演員的目的。 但是它會轉換指針,而不是指針指向的對象

暫無
暫無

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

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