[英]c casting a pointer to a char array as an int* gives the same result as casting a char* as an int*
考慮下面的C程序:
#include <stdio.h>
#include <stdlib.h>
int main(){
char c[1] = {'Q'};
printf("%c ",*(char*)(c)); // line 1
printf("%c\n",*(char*)(&c)); // line 2
}
輸出是QQ
這是我對應該發生的情況的理解,c是指向char的指針,因此第1行打印的char應該是字母Q,因為指向char的指針被轉換為指向char的指針(因此什么也沒有發生),然后已取消引用。 因為c指向的字符是'Q',所以第1行打印'Q'。 這對我來說似乎很有意義。
但是第2行則沒有。 c的地址被強制轉換為指向char的指針,因此我認為應該發生的事是在取消引用表達式*(char *)(&c)后應簡化為指針c的值,但應將其表示為char。
這些都給出相同的結果,我不認為這是巧合,因為我已經在許多不同的字母上嘗試過。 我想知道為什么會這樣。 謝謝
PS:
我嘗試了這個:
#include <stdio.h>
#include <stdlib.h>
int main(){
char c[10] = "asdf";
printf("%c ",*(char*)(c)); // line 1
printf("%c\n",*(char*)(&c)); // line 2
}
我得到這個: aa
在聲明中
char c[1] = {'Q'};
c
是char數組和array name
即c
本身表示該數組的基地址。 如果打印c
和&c
,則結果相同。
注意: c
表示其指向數組第一個元素的指針, &c
表示其指向整個數組的指針。
int main(void){
char c[1] = {'Q'};
printf("%p %p\n",(void*)c,(void*)&c); /* bot results the same */
return 0;
}
這就是為什么*(char*)(c)
和*(char*)(&c)
得出相同結果的原因。 例如
char c[10] = "asdf"; /* lets assume base address of c is 0x100 */
看起來像
--------------------------------------
| a | s | d | f | \0 |
--------------------------------------
0x100 0x101 0x102 ..
c
接下來如何執行這兩個表達式*(char*)(c)
和*(char*)(&c)
。
*(char*)(c) => *(char*)(0x100) => typecasted as char* means c points to 1 byte memory
=> *(0x100) => value in the first byte from 0x100 to 0x101 => a
和
*(char*)(&c) => *(char*)(&(0x100)) => *(char*) (0x100) => c and &c are same
=> *(0x100) => value in the first byte from 0x100 to 0x101 => a
如果考慮等式(void*) c == (void*) &c
,您將意識到它在邏輯上是正確的。 以一個靜態分配的整數為例:
int myvar = 2;
打印myvar
的值很有意義,因為它是一個整數並且可以“普遍”識別。
現在如何識別數組? 顯然帶有該存儲器的地址。
但是,如何打印呢? 沒有規則。 如果沒有理由這樣做,區分c
和&c
有什么意義呢? 可以推測c
可以解釋為數組的第一個元素,但是您可以想象這種選擇的所有缺點。
編譯器的推理實際上是不同的,特別是因為變量不存在,因此它用可以使用的變量替換了它們。
以以下片段為例:
int a = 2;
char c[6] = {'a', 'b', 'c', 'd', 'e', '\0'};
printf("%p\n", c);
printf("%p\n", (void*) &c);
printf("%d\n", a);
printf("%p\n", (void*) &a);
這是gcc
生成的生成的程序集(intel語法):
mov DWORD PTR [rbp-4], 2 # int a = 2;
mov BYTE PTR [rbp-16], 97 # char c[6] = {'a', 'b', 'c', 'd', 'e', '\0'};
mov BYTE PTR [rbp-15], 98
mov BYTE PTR [rbp-14], 99
mov BYTE PTR [rbp-13], 100
mov BYTE PTR [rbp-12], 101
mov BYTE PTR [rbp-11], 0
lea rax, [rbp-16] # printf("%p\n", c);
mov rsi, rax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
lea rax, [rbp-16] # printf("%p\n", (void*) &c);
mov rsi, rax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, DWORD PTR [rbp-4] # printf("%d\n", a);
mov esi, eax
mov edi, OFFSET FLAT:.LC1 [complete object constructor] [complete object constructor]
mov eax, 0
call printf
lea rax, [rbp-4] # printf("%p\n", (void*) &a);
mov rsi, rax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
編譯器以相同的方式解釋c
和&c
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.