声明types的指针?
我刚刚读到,我们需要指定types的指针,而在C(或C ++)中声明它们,即:
int *point ;
据我所知,指针存储variables的地址,地址占用相同数量的内存,无论types如何。 那么,为什么我们需要声明它的types呢?
types安全。 如果你不知道p
应该指向什么,那么就没有什么可以防止类似的错误
*p = "Nonsense"; int i = *p;
静态types检查是防止这种types的错误的一个非常强大的工具。
C和C ++也支持指针运算 ,只有在目标types的大小已知时才能运行。
地址占用相同数量的内存,无论我是什么types
对于当今stream行的平台来说,情况是如此。 但是有些情况并非如此。 例如,指向多字节字的指针可能小于指向单个字节的指针,因为它不需要表示字中字节的偏移量。
因为:
- 不同types的地址不需要具有相同的大小 。 标准明确规定了( C 2011标准 (在线草案),6.2.5 / 28)。
- types安全性:这允许编译器检测何时提供不兼容的函数指针或赋值。 这反过来可以防止丑陋的情况下,你弄乱了函数的参数顺序。
- 当指针被解除引用时,编译器需要知道types。
- 做指针算术,指向的对象的大小需要知道,因此它的types。
最后两点不适用于void
指针,这就是为什么它们不能被解除引用,并且不能对它们进行指针运算。 该标准指定一个void
指针必须足够大以容纳任何types的指针(除了函数指针,这是完全不同的故事),并且可以在没有强制转换的情况下进行void
指针的分配(至less在C中,在C ++中总是需要投) 。
一个原因是在指针运算。 除非知道p
指向的元素的大小 – 即p
是指针的types的大小,否则不能执行p+1
。 如果你想在一个void *p
上尝试p+1
,你很可能会得到一个不好的答案(就像在char *
上做的一样),但也许你不想要这个;它被抓住了,作为错误的警告和错误)。
另一个原因是types安全。 如果一个函数接收到一个int *
参数,那么你不能在这里传递一个指向char
(一个string)的指针。 你会得到一个警告(一个错误-pedantic-errors
/ -pedantic-errors
)。 考虑这个(虚拟)代码:
void test(int *x) { } int main() { char *x = "xyz"; test(x); return 0; }
编译(使用gcc (GCC) 4.8.2 20131017 (Red Hat 4.8.2-1)
)给出:
1.c: In function 'main': 1.c:8:2: warning: passing argument 1 of 'test' from incompatible pointer type [enabled by default] test(x); ^ 1.c:1:6: note: expected 'int *' but argument is of type 'char *' void test(int *x) ^
那么,为什么我们需要声明它的types呢?
你想知道指针的types,所以你可以做静态types检查 。
我们还需要知道types,以便使指针运算起作用,例如,当我们索引到不同大小types的数组( 相当于指针运算 )时,指针将按types相关的数量进行调整。 如果我们看看C99标准的草案部分6.5.6
添加剂操作员说( 强调我的 ):
另外,两个操作数都应该有算术types,或者一个操作数应该是一个指向对象types的指针 […]
所以指针需要是一个对象types ,这意味着不完整或无效。
你还说:
地址占用相同数量的内存,无论types如何。 那么,为什么我们需要声明它的types呢?
这在C ++中并不总是正确的,指向成员函数的指针的大小可以根据类的types而改变,其中涵盖了这个指向成员函数的指针是非常奇怪的动物之一 。
此外,我们可以看到,C99标准草案部分6.2.5
types的第27段说:
[…]指向其他types的指针不需要具有相同的表示或alignment要求。
和C ++标准草案部分3.9.2
复合types第3段说:
[…]指针types的值表示是实现定义的。 指向布局兼容types的cv-qualified和cv-unqualified版本(3.9.3)的指针应具有相同的值表示和alignment要求(3.11)。 […]
除特殊情况外,不要求指针具有相同的表示 。
您需要按照标准要求来指定types。 而且,当您尝试执行像加法或减法这样的指针运算时,没有任何问题。
虽然处理器通常具有“从地址加载字节”,“从地址加载16位半字”和“从地址加载32位字”的不同指令,对于“存储”操作,C使用相同的语法从地址加载一个字节,以加载任何其他大小的值。 鉴于声明:
int n = *p;
编译器可以生成从p中的地址加载字节,半字或字并将其存储到n中的代码; 如果p是一个* float,它可能会产生一个更复杂的代码序列来加载c中的浮点值,截断它,转换为int,并将转换后的值存储到n中。 不知道p的types,编译器不知道哪个操作是合适的。
同样,语句p++
可能会增加p++
的地址一个,两个,四个或其他数字。 地址增加的数量将在声明的p的types上。 如果编译器不知道p的types,它将不知道如何调整地址。
可以声明一个指针而不指定它指向的东西的types。 这种指针的types是void*
。 然而,在做任何有用的事情之前,必须将void*
转换为真正的指针types。 void*
的主要用处在于,如果一个指针被转换为void*
,那么它可以作为一个void*
被代码传递,这个代码对指针的实际types一无所知。 如果指针最终被赋予了知道其types的代码,并且该代码将指针转换回该types,则结果将与已转换为void*
的指针相同。
必须处理指向它一无所知事物的代码的代码通常可以有用地将void*
用于这样的目的,但是知道指针指向的事物的代码通常应该声明适当types的指针。
在解引用和指针算术的时候,指针的types就会起作用。 例如
int x=10; //Lets suppose the address of x=100 int *ptr=&x; //ptr has value 100 printf("The value of x is %d", *ptr); ptr++; // ptr has value 104(if int is 4bytes)
在上面的例子中,指针types是int,因此编译器将从内存地址100开始查找存储在接下来的4个字节(如果int是4字节)中的值。所以指针的types告诉编译器它应该有多less字节寻找解引用。 如果指针types不存在,那么编译器将如何知道在解引用时要查看多less个字节。 而当我们做了ptr ++的指针types告诉多lessptr应该增加。 这里ptr增加4。
char c='a'; //Lets suppose the address of c = 200 char* ptr=&c; //ptr has value 200 ptr++; //ptr has value 201(char assumed to be 1 byte)
指针types告诉ptr增加1个字节。
这样它可以执行算术和其他操作。 考虑这两个例子:
int* p; /* let the address of the memory location p pointing to be 1000*/ p++; printf("%u",p); /* prints 1004 since it is an integer pointer*/ char *p; /* let the address of the memory location p pointing to be 1000*/ p++; printf("%u",p); /* prints 1001 since it is an char pointer*/
我希望这可以帮助你 !
我们实际上不需要 (见下文)来声明types,但我们应该 。 指针存储关于对象位置的信息,而types定义了在内存中占用多less空间。
存储在指针内存中的对象的大小在各种情况下都是需要的 – 创build数组,创build,分配内存,最后使用new
创build对象。
但是你仍然可以定义一个void
指针,如果你想隐藏(出于任何原因)types:
void* dontKnowWhatTypeIsHere;
一个空指针被认为是一个普遍的指针。 它可以指向任何对象,当我们想要使用它的types,我们只会做reinterpret_cast
。
很多前面的陈述,但是apan纯粹是正确的。 现在你的问题为什么我们定义types的指针? 指针的第一个定义一个可以容纳另一个variables地址的指针。 以上定义是部分的。 确切的定义是指针是一个variables,它可以保存一个variables的地址,如果我们去引用(取值),它将返回该地址上的当前值。 如果指针无法在解引用上返回一个值,那么它不是一个指针。 你可以尝试,即使在gcc编译器中,一个简单的variables也可以保存另一个variables的地址,但是在解引用的时候会给你一个错误。 现在的大小无论数据types如何,指针的大小总是等于特定编译器的整数大小。 所以gcc编译器中指针的大小是4字节(整数的大小),在turboc中它的大小是2字节(整数的大小)。 现在问题是为什么等于整数的大小。 什么将是任何variables的地址,它可能是int,char,float等地址总是一个整数,整数的整数存储在int中。 这就是为什么指针的大小等于int的大小,因为它也存储始终是纯整数数据的地址。 那么int和char之间的区别是什么其他数据types的指针。 在检索的时候,你的编译器会根据你的数据types提取字节数,否则你会得到错误或者不是错误,但是对于你来说有些不可预知的结果,但是对我来说却不是这样。 同样的规则适用于递增和递减指针,它总是根据指针数据types递增和递减。 指针的大小并不取决于数据types,因此你的链接列表出现的原因是因为如果你试图在同一个variables中声明结构,那么你会得到编译时错误,因为你的编译器的大小不是结构之前,它的完整的声明,但同样的结构的自我指针指针允许为什么? 唯一的答案是因为指针的大小不取决于数据types的大小。 如果你有任何疑问,然后请问我。 感谢asif aftab