网站空间申请,微信平台微商城,有专门做序列图的网站,小程序二次开发多少钱0. 指针到底是什么#xff1f;
在我们讨论指针的定义之前#xff0c;让我们先了解一下当我们编写时会发生什么 int digit 42; 编译器保留一块内存来保存int值。该块的名称为digit#xff0c;该块中存储的值为42。现在#xff0c;为了记住该块#xff0c;它被分配了一个地…0. 指针到底是什么
在我们讨论指针的定义之前让我们先了解一下当我们编写时会发生什么 int digit 42; 编译器保留一块内存来保存int值。该块的名称为digit该块中存储的值为42。现在为了记住该块它被分配了一个地址或一个位置号例如 24650。
位置编号的值对我们来说并不重要因为它是一个随机值。但是我们可以使用与符号或运算符地址来访问该地址如下所示。 printf(The address of digit %d.,digit);/* prints The address of digit 24650. */ 现在我们可以使用另一个运算符星号digit从变量的地址获取变量的值称为间接或取消引用或地址运算符的值。* printf(The value of digit %d., *(digit);/* prints The value of digit 42. */ 1. 指针定义和表示法
的地址digit可以存储在另一个称为指针变量的变量中。将变量地址存储到指针的语法是 dataType *pointerVariableName variableName; 对于我们的digit变量可以写成 int *addressOfDigit digit; 或者 int *addressOfDigit;
addressOfDigit digit; 这可以理解为 -指向int整数addressOfDigit存储address of() digit变量的指针。
需要理解的几点——
1. dataType- 我们需要告诉计算机我们要存储其地址的变量的数据类型是什么。这里int是 的数据类型digit。
这并不意味着addressOfDigit将存储类型的值int。
整数指针如addressOfDigit只能存储整数类型变量的地址。 int variable1;
int variable2;
char variable3;
int *addressOfVariables; variable1在这里我们可以将和的地址分配variable2给整数指针 addressOfVariables但不能分配给 variable3因为它的类型是char。我们需要一个字符指针变量来存储其地址。
2. *- 指针变量是一种特殊变量它用于存储另一个变量的地址。为了与其他不存储地址的变量区分开来我们*在声明中使用 , 作为符号。
现在我们可以使用addressOfDigit指针变量来打印地址和值digit如下所示 printf(The address of digit %d., addressOfDigit);/* prints The address of digit 24650. */
printf(The value of digit %d., *addressOfDigit);/*prints The value of digit 42. */ 这里*addressOfDigit是被读取为存储在地址处的值addressOfDigit。
请注意我们使用的格式%d标识符。嗯这并不完全正确。要使用的正确标识符是。addressOfDigit%p
使用%p地址以十六进制值显示。但内存地址可以以整数和八进制值显示。尽管如此由于这不是完全正确的方法因此会显示警告。 int num 5;
int *p num;
printf(Address using %%p %p,p);
printf(Address using %%d %d,p);
printf(Address using %%o %o,p); 根据我使用的编译器的输出是 - Address using %p 000000000061FE00
Address using %d 6422016
Address using %o 30377000 这是您使用时显示的警告%d- warning: format %d expects argument of type int, but argument 2 has type int * 2. 一些特殊提示
1. 野指针 char *alphabetAddress; /* uninitialised or wild pointer */
char alphabet a;
alphabetAddress alphabet; /* now, not a wild pointer */ 当我们定义字符指针时alphabetAddress我们没有初始化它。此类指针称为野指针。它们存储一个垃圾值即我们不知道是否保留的字节的内存地址请记住int digit 42;我们在声明它时保留了一个内存地址。
假设我们取消引用一个野指针并将一个值分配给它指向的内存地址。这将导致意外的行为因为我们将在可能空闲或保留的内存块中写入数据。
2. 空指针
现在为了确保我们没有野指针我们可以用一个NULL值初始化一个指针使其成为空指针。 char *alphabetAddress NULL /* Null pointer */ 空指针不指向任何内容或者指向用户无法访问的内存地址。
3. 空指针
void 指针可用于指向任何数据类型的变量。它可以被重用来指向我们想要的任何数据类型。它被声明为 void *pointerVariableName NULL; 由于它们本质上非常通用因此也称为通用指针。
由于其灵活性void 指针也带来了一些限制。空指针不能像任何其他指针一样取消引用。适当的类型转换是必要的。 void *pointer NULL;
int number 54;
char alphabet z;
pointer number;
printf(The value of number , *pointer); /* Compilation Error */
/* Correct Method */
printf(The value of number , *(int *)pointer); /* prints The value at number 54 */
pointer alphabet;
printf(The value of alphabet , *pointer); /* Compilation Error */
printf(The value of alphabet , *(char *)pointer); /* prints The value at alphabet z */ 类似地void 指针需要进行类型转换才能执行算术运算。
空指针在 C 语言中很有用malloc()。库函数calloc()可以动态分配内存返回空指针。qsort()是 C 中的内置排序函数有一个函数作为其参数该函数本身接受 void 指针作为其参数。
4. 悬空指针
悬空指针指向用于保存变量的内存地址。由于它指向的地址不再被保留使用它会导致意想不到的结果。 main(){int *ptr;ptr (int *)malloc(sizeof(int));*ptr 1;printf(%d,*ptr); /* prints 1 */free(ptr); /* deallocation */*ptr 5;printf(%d,*ptr); /* may or may not print 5 */
} 尽管内存已被释放free(ptr)但指向整数的指针ptr仍然指向该未保留的内存地址。
3. 指针运算
现在我们知道指针与任何其他变量不同。除了内存块的地址之外它们不存储任何值。因此很明显并非所有算术运算都对它们有效。两个指针有地址相乘或相除有意义吗
指针的有效操作 很少但非常有用-
1.只有当一个指针具有相同类型时才可以将它们的值分配给另一个指针除非类型转换或其中一个是void *. int ManU 1;
int *addressOfManU ManU;
int *anotherAddressOfManU NULL;
anotherAddressOfManU addressOfManU; /* Valid */
double *wrongAddressOfManU addressOfManU; /* Invalid */ 2.只能对指针进行整数加减。 int myArray {3,6,9,12,15};
int *pointerToMyArray myArray[0];
pointerToMyArray 3; /* Valid */
pointerToMyArray * 3; /* Invalid */ 当您向指针添加或减去一个整数例如 n时您实际上并不是在字面上添加或减去该整数。您正在添加或减去指针所指向的变量的数据类型大小的 n 倍。 int number 5;/* Suppose the address of number is 100 */
int *ptr number;
int newAddress ptr 3;/* Same as ptr 3 * sizeof(int) */ 存储的值newAddress不会是103而是112.
3.指针的减法和比较仅当两者都是同一数组的成员时才有效。 int myArray {3,6,9,12,15};
int sixthMultiple 18;
int *pointer1 myArray[0];
int *pointer2 myArray[1];
int *pointer6 sixthMuliple;/* Valid Expressions */
if(pointer1 pointer2)
pointer2 - pointer1;/* Invalid Expressions
if(pointer1 pointer6)
pointer2 - pointer6 指针相减得到分隔它们的元素数量。
4.您可以对指针进行赋值或与 进行比较NULL。 上述规则的唯一例外是数组最后一个元素之后的第一个内存块的地址遵循指针算术。 指针和数组同时存在。最有效的指针操作只能通过数组来完成是有原因的。我们将在下一篇文章中用数组讨论上述规则。