指针与数组问题归档

然后就是

Posted by Matrixkook on November 28, 2018

我对指针和数组的理解

指针

某社团的上古学长曾经说过C语言中只有两种类型变量,值和指针。起初我还不太理解学长的意思,直到现在我才渐渐有一点明悟。

即是这两种类型

AnyType   // 创建一个该类型的变量 
AnyType *  // 创建一个指针 这个指针指向的值是一个该类型的变量 

指针也是变量,它本身也有值,它保存了它所指向地址的值。由此,可以通过指针间接修改变量的值,读取变量的值。

数组

数组可以理解为相邻的几块内存,无论是几维数组,都只是系统给出的假像,实际它还是线性排布的。

int  arr[10] // 一个简单的数组 包含10个长度为一个sizeof(int)的空间

数组和指针的联系还是十分紧密的,例如 这个arr[0]在引用时实际上可以写为 (arr + 0)
这也解释了为什么数组会从0开始。

指针数组和数组指针

  1. 指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定。它是“储存指针的数组”的简称。
  2. 数组指针:首先它是一个指针,它指向一个数组。它是“指向数组的指针”的简称。

其实只要分清了这两个概念就不会在搞混了。

指针的数组问题归档

修改const数组

题目要求修改 img

```strcmp_fix(const char * s1, const char * s2) ``

中所指向的 arr1,arr2 字符串 可是这个函数中的变量是 const 类型的指针,就是说 你无法通过 S1S2 来改变 arr1/2 中的值。 由此 我猜想 const 的机制。 1. 仅通过禁止访问 const * 的变量所解引用的变量 的值。 2. 通过禁止修改 const*的值。

总体代码如下

#include <stdio.h>
#include <stdlib.h>
#define lenth 20
void strcmp_fix(const char *s1, const char *s2);
int main(void)
{
    char arr_1[lenth], arr_2[lenth]; // 输入两个带
    测试的字符串
    printf("please enter your first arr \n");
    scanf_s("%s", arr_1, lenth);

    printf("enter your next arr\n");
    scanf_s("%s", arr_2, lenth);
    strcmp_fix(arr_1, arr_2);
    printf("\n%s\n", arr_1);
    printf("\n%s\n", arr_2);

    system("pause");
}
void strcmp_fix(const char *s1, const char *s2)
{
    char *sp1, *sp2; // sp1 sp2 是值等于 const*
    变量的指针 我推测 const 限定符只能保护 S1 / 本身
                                                    sp1 = s1; // sp1/2 的值和 s1/2 一致
    sp2 = s2;
    (*sp1)++;
    (*sp2)++; // 使每一个字符串第一个字符的值加 1
}

运行结果如下: img

成功的修改了 原字符串的首元素的值。

机制分析

我先尝试对 const 解引用后的变量进行一些操作

将代码变为

(*s1)++;

直接报错

说明了 const 类型是不可修改的左值

说明猜想 通过禁止尝试修改 const*的值 是正确的

猜想 通过禁止访问 const * 的变量所解引用的变量的值 我们把上面的代码 改变一下 *s1++; 即是先解引用 s1 所指向的值 arr1++ 系统并没有给出报错,但是对应的,字符串的值也没 有改变。无法通过 s1 间接修改,但是…… 不妨看一下这几个变量的关系

不难发现 虽然不能通过 s1 修改 但是 可以通过 sp1 将 s1 的值提取出来。修改字符串只需要它的地址信息 即可。 Const* 类型并不能保证 它所指向的变量不被修改。

类型转换

题目要求是将任何类型的变量以十六进制(内存中实际的)的方式打印出来。

#include<stdio.h>
#include <stdlib.h>
typedef unsigned char *byte_pointer; // 比特位指针
void show_the_bit(byte_pointer byte_start, size_t lenth);  // 将浮点数改变成
int main(void) { 
    float enter_num = 0.0; 
    scanf_s("%f", &enter_num); // 修改此处可以转换不同的类型
    
    show_the_bit((byte_pointer)&enter_num, sizeof(float)); // 利用强制类型转换 跳过检查
    system("pause");
}
void show_the_bit(byte_pointer start, size_t lenth) 
{ 
	for (size_t i = 1; i < lenth; i++)
	printf("%.2x", start[i++]); 
}

独特的空指针

#include<stdio.h> //中是这样定义的
#if !defined(NULL) && defined(__NEEDS_NULL)
#ifdef __cplusplus
#define NULL    0
#else
#define NULL    ((void *)0)
#endif
#endif

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant//

一个整数常量表达式的值0,或这样的表达式类型void *,称为空指针常量

这里告诉我们:0、0L、’\0’、3 - 3、0 * 17 (它们都是“integer constant expression”)以及 (void)0 (tyc: 我觉得(void)0应该算是一个空指针吧,更恰当一点)等都是空指针常量(注意 (char) 0 不叫空指针常量,只是一个空指针值)。至于系统选取哪种形式作为空指针常量使用,则是实现相关的。

一般的 C 系统选择 (void)0 或者 0 的居多(也有个别的选择 0L); 至于 C++ 系统,由于存在严格的类型转化的要求,void* 不能象 C 中那样自由转换为其它指针类型,所以通常选 0 作为空指针常量(tyc: C++标准推荐),而不选择 (void*)0。