在C语言中,我们可以定义不同类型的指针,例如:
你是对的。 所有指针都具有相同的大小,并且它们具有相同的数据类型(内存地址)。 所以,你的问题是合法的。
编译器需要知道指针指向的数据类型,以便能够找到如何处理它。 例如,数组基本上是指向(最好)分配的存储区域的指针。 因此, a[1]
是*(a+1)
的简写。 但是数组的下一个元素从哪里开始呢? 除非你的指针有一个类型,否则编译器无法知道这一点。 例如,如果你告诉他指向int
(4个字节)并且例如a = 0x100
,他将知道a+1
是0x104
,因为那是下一个元素的地址。
此外,了解指针指向的数据类型对于了解如何取消引用指针(解释数据)至关重要。
这都是关于静态类型检查和指针算术的。 也许最好通过一个具体的例子来说明。
考虑一下:
#include int main( int argc, char *argv[] ) { char x[10]; char *p0 = &x[0]; /* ok */ int *p1 = &x[0]; /* <- type checking, warning #1 */ char (*p2)[10] = &x; /* ok */ int (*p3)[10] = &x; /* <- type checking, warning #2 */ (void)printf( "sizeof(char): %ldn", sizeof( char )); (void)printf( "sizeof(int): %ldn", sizeof( int )); (void)printf( "p0: %p, p0+1: %pn", (void*)p0, (void*)( p0+1 )); (void)printf( "p1: %p, p1+1: %pn", (void*)p1, (void*)( p1+1 )); (void)printf( "p2: %p, p2+1: %pn", (void*)p2, (void*)( p2+1 )); (void)printf( "p3: %p, p3+1: %pn", (void*)p3, (void*)( p3+1 )); return 0; }
重要 :使用-Wall
编译( gcc -Wall -o test test.c
)
该程序将编译,但你会得到两个关于不兼容的指针类型的警告,这是正确的。
% gcc -Wall -o test test.c test.c: In function 'main': test.c:9:21: warning: initialization from incompatible pointer type [enabled by default] int *p1 = &x[0]; /* <- type checking, warning #1 */ ^ test.c:11:21: warning: initialization from incompatible pointer type [enabled by default] int (*p3)[10] = &x; /* <- type checking, warning #2 */ ^
现在运行程序:
% ./test sizeof(char): 1 sizeof(int): 4 p0: 0x7fff9f6dc5c0, p0+1: 0x7fff9f6dc5c1 # + 1 char p1: 0x7fff9f6dc5c0, p1+1: 0x7fff9f6dc5c4 # + 1 int (4 bytes here) p2: 0x7fff9f6dc5c0, p2+1: 0x7fff9f6dc5ca # + 10 chars p3: 0x7fff9f6dc5c0, p3+1: 0x7fff9f6dc5e8 # + 10 ints (40 bytes here)
在这里你可以观察到对指针算术的影响:虽然所有4个指针都被初始化为相同的值,但是相同的操作会产生完全不同的结果。
把它想象成生活空间的不同。 每个住所都有1个地址,但住宅的大小不同。
/* _________________________________________ /___________Studio Apartments_____________ | _ _ _ _ _ _ _ _ _ _ | |_|0|_|1|_|2|_|3|_|4|_|5|_|6|_|7|_|8|_|9|_| _________________________________________ /____________2 Bed Apartments_____________ | _ _ _ _ _ | |_|0|_____|1|_____|2|_____|3|_____|4|_____| Note: different endianness may look like: _________________________________________ /____________2 Bed Apartments_____________ | _ _ _ _ _ | |_____|0|_____|1|_____|2|_____|3|_____|4|_| */ typedef studio char; //tell the compiler what a "studio" is like typedef apt2br short; //tell it what a 2 bedroom apartment is like /*Now let's build our apartments at the first available address.*/ studio mystudios[10] = /*the letter people live here :)*/ {'A','B','E','C','I','D','O','F','U','G'}; /*We just told our contractor to build somewhere - record locations for later.*/ studio *LetterStudios=&mystudios; /* Let's say we want to print out all of our letter people residents * and no one has built an apartment complex next to them, so the data * following our last letter person is () a '0' */ printf("%sn", (char *)LetterStudios); /* if nothing is built we may get "ABECIDOFUG", but since we did not add our * own ' ' terminator then we get whatever happens to be next. This is a * buffer overrun ... we may get "ABECIDOFUG" or worse */
让我们看一下2字节的情况:
/* So let's give ourselves some boundaries and loop through it, but this * case has 1 byte elements, so lets look at a 2 byte array */ apt2br myapts[5] = /*people with magic number names live here :)*/ {0xFEFE, 0xB0B, 0xDADE, 0xABE, 0xBABE}; apt2br *MagicApartments=&myapts; /* to get the number of units in an apartment complex we can always divide the * size of the whole complex by the size of a single unit */ for(int i=0;i
我认为指针只存储了变量的地址。 所以所有指针都有相同的大小(4个字节或8个字节),因为地址总线是32位或64位。 你可以声明像这样的指针
void * p = null; int* p2 = (int*)p; float* p3 = (float*)p;
p
, p2
, p3
指向同一地址。 我们在声明指针时使用的数据类型告诉编译如何处理该地址中的数据。
例如, *p2
将被处理为4字节整数, *p3
将被处理为8字节浮点数。
以上就是c/c++开发分享C中不同类型的指针有什么区别相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注(猴子技术宅)。
”本文来自网络收集,不代表猴子技术宅立场,如涉及侵权请点击右边联系管理员删除。
如若转载,请注明出处:https://www.ssfiction.com/c-cyuyankaifa/545971.html