使用以下序列声明指针。
[storage-class-specifiers] [cv-qualifiers] type-specifiers [ms-modifier] declarator ;
其中,任何有效指针声明符均可用于 declarator。简单指针声明符的语法如下所示:
* [cv-qualifiers] identifier [= expression]
1.声明说明符:
可选存储类说明符。
应用于要指向的对象的类型的可选 const 或 volatile 关键字。
类型说明符:可表示要指向的对象的类型的类型名称。
2.声明符:
可选的 Microsoft 专用修饰符。
* 运算符。
应用于指针本身的可选 const 或 volatile 关键字。
标识符。
可选初始值设定项。
指向函数的指针的声明符类似于以下形式:
(* [cv-qualifiers] identifier )( argument-list ) [cv-qualifers] [exception specification] [= expression];
对于指针数组,语法如下所示:
* identifier [ [ constant-expression ] ]
但是,指针声明符可能更复杂。
多个声明符及其初始值设定项可能同时出现在前面有声明说明符且以逗号分隔的列表中的一个声明中。
指针声明的简单示例如下:
char *pch;
前面的声明指定 pch 指向 char 类型的对象。
更复杂的示例是
static unsigned int * const ptr;
前面的声明指定 ptr 是一个指向 unsigned int 类型(带静态存储持续时间)的对象的常量指针。
下一个示例演示如何声明和初始化多个指针:
static int *p = &i, *q = &j;
在前面的示例中,指针 p 和 q 都指向类型 int 的对象并分别初始化为 i 和 j 的地址。存储类说明符 static 应用于这两个指针。
// pointer.cpp // compile with: /EHsc #include <iostream> int main() { int i = 1, j = 2; // local variables on the stack int *p; // a pointer may be assigned to "point to" the value of // another variable using the & (address of) operator p = & j; // since j was on the stack, this address will be somewhere // on the stack. Pointers are printed in hex format using // %p and conventionally marked with 0x. printf_s("0x%p\n", p); // The * (indirection operator) can be read as "the value // pointed to by". // Since p is pointing to j, this should print "2" printf_s("0x%p %d\n", p, *p); // changing j will change the result of the indirection // operator on p. j = 7; printf_s("0x%p %d\n", p, *p ); // The value of j can also be changed through the pointer // by making an assignment to the dereferenced pointer *p = 10; printf_s("j is %d\n", j); // j is now 10 // allocate memory on the heap for an integer, // initialize to 5 p = new int(5); // print the pointer and the object pointed to // the address will be somewhere on the heap printf_s("0x%p %d\n", p, *p); // free the memory pointed to by p delete p; // At this point, dereferencing p with *p would trigger // a runtime access violation. // Pointer arithmetic may be done with an array declared // on the stack or allocated on the heap with new. // The increment operator takes into account the size // of the objects pointed to. p = new int[5]; for (i = 0; i < 5; i++, p++) { *p = i * 10; printf_s("0x%p %d\n", p, *p); } // A common expression seen is dereferencing in combination // with increment or decrement operators, as shown here. // The indirection operator * takes precedence over the // increment operator ++. // These are particularly useful in manipulating char arrays. char s1[4] = "cat"; char s2[4] = "dog"; char* p1 = s1; char* p2 = s2; // the following is a string copy operation while (*p1++ = *p2++); // s2 was copied into s1, so now they are both equal to "dog" printf_s("%s %s", s1, s2); }
输出:
0x0012FEC8 0x0012FEC8 2 0x0012FEC8 7 j is 10 0x00320850 5 0x00320850 0 0x00320854 10 0x00320858 20 0x0032085C 30 0x00320860 40 dog dog
另一个示例演示如何在数据结构中使用指针;本例中采用链接列表。
// pointer_linkedlist.cpp // compile with: /EHsc #include <iostream> using namespace std; struct NewNode { NewNode() : node(0){} int i; NewNode * node; }; void WalkList(NewNode * ptr) { if (ptr != 0) { int i = 1; while (ptr->node != 0 ) { cout << "node " << i++ << " = " << ptr->i << endl; ptr = ptr->node; } cout << "node " << i++ << " = " << ptr->i << endl; } } void AddNode(NewNode ** ptr) { NewNode * walker = 0; NewNode * MyNewNode = new NewNode; cout << "enter a number: " << endl; cin >> MyNewNode->i; if (*ptr == 0) *ptr = MyNewNode; else { walker = *ptr; while (walker->node != 0) walker = walker->node; walker->node = MyNewNode; } } int main() { char ans = ' '; NewNode * ptr = 0; do { cout << "a (add node) d (display list) q (quit)" << endl; cin >> ans; switch (ans) { case 'a': AddNode(&ptr); break; case 'd': WalkList(ptr); break; } } while (ans != 'q'); }
输出:
a 45 d a 789 d qa (add node) d (display list) q (quit) enter a number: a (add node) d (display list) q (quit) node 1 = 45 a (add node) d (display list) q (quit) enter a number: a (add node) d (display list) q (quit) node 1 = 45 node 2 = 789 a (add node) d (display list) q (quit)
固定和可变指针
const 和 volatile 关键字用于更改处理指针的方式。 const 关键字指定指针在初始化后无法修改;此后指针将受到保护,防止进行修改。
volatile 关键字指定与后跟的名称关联的值可由用户应用程序中的操作以外的操作修改。因此,volatile 关键字对于声明共享内存中可由多个进程访问的对象或用于与中断服务例程通信的全局数据区域很有用。
如果某个名称被声明为 volatile,则每当程序访问该名称时,编译器都会重新加载内存中的值。这将显著减少可能的优化。但是,当对象的状态可能意外更改时,这是保证可预见的程序html" target="_blank">性能的唯一方法。
若要将指针指向的对象声明为 const 或 volatile,请使用以下形式的声明:
const char *cpch; volatile char *vpch;
若要将指针的值(即指针中存储的实际地址)声明为 const 或 volatile,请使用以下形式的声明:
char * const pchc; char * volatile pchv;
C++ 语言会阻止将允许修改声明为 const 的对象或指针的赋值。此类赋值会移除用来声明对象或指针的信息,从而违反原始声明的意图。请考虑以下声明:
const char cch = 'A'; char ch = 'B';
假定前面声明了两个对象(const char 类型的 cch 和 char 类型的 ch),以下声明/初始化将是有效的:
const char *pch1 = &cch; const char *const pch4 = &cch; const char *pch5 = &ch; char *pch6 = &ch; char *const pch7 = &ch; const char *const pch8 = &ch;
以下声明/初始化存在错误。
char *pch2 = &cch; // Error char *const pch3 = &cch; // Error
pch2 的声明声明了一个可以用来修改常量对象的指针,因此不允许使用。 pch3 的声明指定 pointer 是常量,而不是对象;与不允许使用 pch2 的原因相同,也不允许使用该声明。
以下八个赋值显示了通过指针进行的赋值以及对前面的声明的指针值的更改;现在,假设 pch1 到 pch8 的初始化是正确的。
*pch1 = 'A'; // Error: object declared const pch1 = &ch; // OK: pointer not declared const *pch2 = 'A'; // OK: normal pointer pch2 = &ch; // OK: normal pointer *pch3 = 'A'; // OK: object not declared const pch3 = &ch; // Error: pointer declared const *pch4 = 'A'; // Error: object declared const pch4 = &ch; // Error: pointer declared const
声明为 volatile 或 const 和 volatile 的组合的指针遵循相同的规则。
指向 const 对象的指针通常用于函数声明中,如下所示:
errno_t strcpy_s( char *strDestination, size_t numberOfElements, const char *strSource );
前面的语句声明了函数 strcpy_s,其中,三个参数中的两个是指向 char 的类型指针。由于参数是按引用而不是按值传递的,因此,如果未将 strSource 声明为 const,则该函数可以自由修改 strDestination 和 strSource。将 strSource 声明为 const 可向调用方保证调用的函数无法更改 strSource。
注意
由于存在从 typename * 到 const typename * 的标准转换,因此将 char * 类型的参数传递到 strcpy_s 是合法的。但是,反之则不行;不存在从对象或指针中移除 const 特性的隐式转换。
给定类型的 const 指针可以分配给同一类型的指针。但是,非 const 类型的指针不能赋给 const 指针。以下代码显示了正确和错误的赋值:
// const_pointer.cpp int *const cpObject = 0; int *pObject; int main() { pObject = cpObject; cpObject = pObject; // C3892 }
以下示例显示了当有指针指向某个指向对象的指针时如何将对象声明为 const。
// const_pointer2.cpp struct X { X(int i) : m_i(i) { } int m_i; }; int main() { // correct const X cx(10); const X * pcx = &cx; const X ** ppcx = &pcx; // also correct X const cx2(20); X const * pcx2 = &cx2; X const ** ppcx2 = &pcx2; }
本文向大家介绍C++编程中的命名空间基本知识讲解,包括了C++编程中的命名空间基本知识讲解的使用技巧和注意事项,需要的朋友参考一下 命名空间是一个声明性区域,为其内部的标识符(类型、函数和变量等的名称)提供一个范围。命名空间用于将代码组织到逻辑组中,还可用于避免名称冲突,尤其是在基本代码包括多个库时。命名空间范围内的所有标识符彼此可见,而没有任何限制。命名空间之外的标识符可通过使用每个标识符的完全
指针变量的值为内存地址。通常变量直接包含特定值,而指针则包含特定值变量的地址。因此可以说,变量名直接(directly)引用数值,而指针间接(indirectly)引用数值(如图 5.1 通过指针引用数值称为间接引用。 指针和任何其他变量一样,应先声明后使用。下列声明: int *countPtr, count; 声明变量 countPtr 的类型为 int*(即指向整型值的指针),或者说成 co
typora-copy-images-to: images 尽管在Java中没有显式的使用指针并且也不允许程序员使用指针,而实际上对象的访问就是使用指针来实现的。一个对象会从实际的存储空间的某个位置开始占据一定数量的存储体。该对象的指针就是一个保存了对象的存储地址的变量,并且这个存储地址就是对象在存储空间中的起始地址。在许多高级语言中指针是一种数据类型,而在Java中是使用对象的引用来替代的。 考
本文向大家介绍对C语言中指针的理解与其基础使用实例,包括了对C语言中指针的理解与其基础使用实例的使用技巧和注意事项,需要的朋友参考一下 C语言的指针,关键意思在于“指”。 “指”是什么意思? 其实完全可以理解为指示的意思。比如,有一个物体,我们称之为A。正是这个物体,有了这么个称谓,我们才能够进行脱离这个物体的实体而进行一系列的交流。将一个物体的指示,是对这个物体的抽象。有了这种抽象能力,才有所谓
问题内容: 我是Java菜鸟。我已经掌握了将C / C ++指针转换为Java引用的概念,并且进展相当顺利。 我打了一段有指针的代码(即* ptr)。我需要取消引用指针并更改其指向的指针的值(即 ptr =&newthing;) 在Java中这似乎要困难得多。是否有人对如何解决此问题有任何想法?快速谷歌搜索什么都没有。 这是C ++中的代码示例。我想在Java中获得类似的工作,但是ptr_to_p
问题内容: 我一直在玩Go制作一些数据结构库,这是一个大问题。我希望数据结构能够包含任何类型,但是在Go中我看不到任何方法可以执行此操作,因为您无法声明空指针,并且它们没有像NSObject这样的类,所有对象都可以从中继承。如何在Go中实现相同的功能? 问题答案: 根据Go编程语言规范: 类型实现包含其方法的任何子集的任何接口,因此可以实现几个不同的接口。例如,所有类型都实现 空接口 : 如果您在