让我们一起来对C语言指针再分析

目录
  • 初次认识指针,我们大概了解到一下知识。
  • 第一站 字符指针----存放字符地址的指针
    • 1.使用方法
    • 2. 指针数组----存放指针的数组
    • 3. 数组指针
      • 3.1 数组指针的定义
      • 3.2 &数组名VS数组名
      • 3.3 数组指针的使用
  • 总结

初次认识指针,我们大概了解到一下知识。

1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。

2. 指针的大小是固定的 4/8 个字节( 32 位平台 /64 位平台)。

3. 指针是有类型,指针的类型决定了指针的 +- 整数的步长,指针解引用操作的时候的权限。

4. 指针的运算。 下面我们再来对指针这个大佬,做一个进一步的剖析

第一站 字符指针----存放字符地址的指针

1.使用方法

(1)直接使用字符

int main()
{
    char ch = 'w';
    char *pc = &ch;
    *pc = 'w';
    return 0;
 }

(2)字符串用 “” 使用

int main()
{
    const char* pstr = "hello bit.";
//这里是把一个字符串放到pstr指针变量里了吗?
    printf("%s\n", pstr);
    return 0;
 }

我们知道一个指针变量的大小是4byte,显然这里不可能存放一整个字符串。

实际上存入ptr的是‘ h ’的地址。

有点类似于数组名再一般情况下表示数组首元素地址而非整个数组。

为了加深对他的理解,我们来看下面这串代码

#include <stdio.h>
int main()
{
    char str1[] = "hello bit.";
    char str2[] = "hello bit.";
    const char *str3 = "hello bit.";
    const char *str4 = "hello bit.";
    if(str1 ==str2)
 printf("str1 and str2 are same\n");
    else
 printf("str1 and str2 are not same\n");
    if(str3 ==str4)
 printf("str3 and str4 are same\n");
    else
 printf("str3 and str4 are not same\n");
    return 0;
 }

 结果是

数组再内存中是通过压栈的方式储存的,所以使用数组是我们需要小心避免栈溢出这一类问题。而“ abcedf ”属于常量字符串,它是存放在内存的静态区上的。str3和str4指向同一个空间,自然就相等啦。

对字符指针的介绍就暂时到此,期待下次和它的见面。

2. 指针数组----存放指针的数组

int* arr1[10]; //整形指针的数组
//数组元素 10个 int*
char *arr2[4]; //一级字符指针的数组
//数组元素 4个 char*
char **arr3[5];//二级字符指针的数组
//数组元素 5个 char*

想要确定指针所指向的内容是什么,我有一个好方法要分享给大家

去掉变量名,即得到变量类型

3. 数组指针

3.1 数组指针的定义

数组指针是指针?还是数组?

答案是:指针。 

我们已经熟悉:

整形指针: int * pint; 能够指向整形数据的指针。

浮点型指针: float * pf; 能够指向浮点型数据的指针。

那数组指针应该是:能够指向数组的指针。

下面代码哪个是数组指针?

int *p1[10];
int (*p2)[10];
//p1, p2分别是什么?

解释:

p2先和*结合,说明p2是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。

p1 先和[]结合,说明 p1是一个数组 ,数组元素是10个 int* 类型的元素

注意 [ ]的优先级高于 * 

3.2 &数组名VS数组名

对于下面的数组:

arr 和 &arr 分别是啥?

我们知道arr是数组名,数组名表示数组首元素的地址。

那&arr数组名到底是啥?

我们看一段代码: 

#include <stdio.h>
int main()
{
    int arr[10] = {0};
    printf("%p\n", arr);
    printf("%p\n", &arr);
    return 0;
}

结果是 两者的地址相同。

可见数组名和 & 数组名打印的地址是一样的。 难道两个是一样的吗? 我们再来看下面这段代码

#include <stdio.h>
int main()
{
 int arr[10] = { 0 };
 printf("arr = %p\n", arr);
 printf("&arr= %p\n", &arr);
 printf("arr+1 = %p\n", arr+1);
 printf("&arr+1= %p\n", &arr+1);
 return 0;
}

我们发现虽然arr和&arr的地址相同,但是他们+1后的结果却是大相径庭的。

为什么呢?

实际上: 

&arr 表示的是 数组的地址 ,而不是数组首元素的地址。(细细体会一下) 本例中 &arr 的类型是: int(*)[10] ,是一种数组指针类型 数组的地址 +1 ,跳过整个数组的大小,所以 &arr+1 相对于 &arr 的差值是 40

3.3 数组指针的使用

那数组指针是怎么使用的呢? 既然数组指针指向的是数组,那数组指针中存放的应该是数组的地址。

看代码:

一个数组指针的使用:

#include <stdio.h>
int main()
{
   int arr[10] = {1,2,3,4,5,6,7,8,9,0};
   int (*p)[10] = &arr;//把数组arr的地址赋值给数组指针变量p
   //但是我们一般很少这样写代码
   return 0;
}
 

一个数组指针的使用:

#include<stdio.h>
//用下表来打印数组
void print_arr1(int arr[3][5], int row, int col)
{
	int i = 0;int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
//用指针来打印数组
void print_arr2(int(*arr)[5], int row, int col) {
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 };
	print_arr1(arr, 3, 5);
	//数组名arr,表示首元素的地址
	//但是二维数组的首元素是二维数组的第一行
	//所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址
	//可以数组指针来接收
	print_arr2(arr, 3, 5);
	return 0;
}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • C语言创建链表错误之通过指针参数申请动态内存实例分析

    本文实例讲述了C语言创建链表中经典错误的通过指针参数申请动态内存,分享给大家供大家参考之用.具体实例如下: #include <stdio.h> #include <stdlib.h>// 用malloc要包含这个头文件 typedef struct node { int data; struct node* next;// 这个地方注意结构体变量的定义规则 } Node; void createLinklist(Node* pHder, int length) { int i =

  • C语言基础野指针与空指针示例分析

    目录 一:野指针 1.1 :野指针的成因 2.1 :规避野指针 1. 初始化指针 2. 避免指针越界 3 避免返回局部变量的地址 4. 开辟的指针释放后置为NULL 5. 养成良好的编程习惯 二:空指针 一:野指针 概念:野指针就是指向的内存地址是未知的(随机的,不正确的,没有明确限制的). 说明:指针变量也是变量,是变量就可以任意赋值.但是,任意数值赋值给指针变量没有意义,因为这样的指针就成了野指针,此指针指向的区域是未知(操作系统不允许操作此指针指向的内存区域). 注:野指针不会直接引发错误

  • C语言指针的长度和类型深入分析

    指针是C语言的精髓,本文就以实例的形式详细分析了C语言的长度和类型.对于初学者深入理解C语言程序设计有很好的参考价值.具体分析如下: 一般来说,如果考虑应用程序的兼容性和可移植性,指针的长度就是一个问题,在大部分现代平台上,数据指针的长度通常是一样的,与指针类型无关,尽管C标准没有规定所有类型指针的长度相同,但是通常实际情况就是这样.但是函数指针长度可能与数据指针的长度不同. 指针的长度取决于使用的机器和编译器,例如:在现代windows上,指针是32位或是64位长 测试代码如下: #inclu

  • C语言中指针和数组试题详解分析

    目录 数组题: 程序一(一维数组): 字符数组 程序二(字符数组): 程序三(字符数组): 程序四(字符数组): 程序五(字符数组): 二维数组 程序六( 二维数组): 指针题 程序七( 指针): 程序八( 指针): 程序九( 指针): 程序十( 指针): 程序十( 图): 程序十一( 指针): 程序十二( 指针): 程序十三( 指针): 指针 和 数组 试题解析 小编,在这里想说一下,c语言的最后一节 C预处理,可能还需要一些时间,因为小编,昨天才下载了虚拟机 和 linux 系统,还没开始安

  • C语言中的数组和指针汇编代码分析实例

    今天看<程序员面试宝典>时偶然看到讲数组和指针的存取效率,闲着无聊,就自己写了段小代码,简单分析一下C语言背后的汇编,可能很多人只注重C语言,但在实际应用当中,当出现问题时,有时候还是通过分析汇编代码能够解决问题.本文只是为初学者,大牛可以飘过~ C源代码如下: 复制代码 代码如下: #include "stdafx.h" int main(int argc, char* argv[]) {        char a=1;        char c[] = "

  • C语言编程const遇上指针分析

    const关键字 可以有很多用处,比如: #define ROW 10 就代表ROW的值恒为10,不可修改. 而 const int ROW=10; 也可以将值恒定,无法修改.还有 const int num[10];//将数组整个保护,无法修改. 但,并不是将被保护量变为常量,而是在处理时将其看为常量,不能对其修改. 当const与指针结合 我们先来看看这个 const int num[] = { 1,2,3,4,5 }; int* p = num; num[0] = 10; *p = 10;

  • c语言:基于函数指针的两个示例分析

    第一个:------------------------------------------------------ 复制代码 代码如下: #include <stdio.h>#include <string.h>void tell_me(int f(const char *, const char *));int main(void){   tell_me(strcmp);   tell_me(main);   return 0;}void tell_me(int f(const

  • 让我们一起来对C语言指针再分析

    目录 初次认识指针,我们大概了解到一下知识. 第一站 字符指针----存放字符地址的指针 1.使用方法 2. 指针数组----存放指针的数组 3. 数组指针 3.1 数组指针的定义 3.2 &数组名VS数组名 3.3 数组指针的使用 总结 初次认识指针,我们大概了解到一下知识. 1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间. 2. 指针的大小是固定的 4/8 个字节( 32 位平台 /64 位平台). 3. 指针是有类型,指针的类型决定了指针的 +- 整数的步长,指针解引用操作的

  • Go语言指针使用分析与讲解

    普通指针 和C语言一样, 允许用一个变量来存放其它变量的地址, 这种专门用于存储其它变量地址的变量, 我们称之为指针变量 和C语言一样, Go语言中的指针无论是什么类型占用内存都一样(32位4个字节, 64位8个字节) package main import ( "fmt" "unsafe" ) func main() { var p1 *int; var p2 *float64; var p3 *bool; fmt.Println(unsafe.Sizeof(p1

  • C语言指针详解及用法示例

    新手在C语言的学习过程中遇到的最头疼的知识点应该就是指针了,指针在C语言中有非常大的用处.下面我就带着问题来写下我对于指针的一些理解. 指针是什么? 指针本身是一个变量,它存储的是数据在内存中的地址而不是数据本身的值.它的定义如下: int a=10,*p; p=&a int a=10; int *p=&a; 首先我们可以理解 int* 这个是要定义一个指针p,然后因为这个指针存储的是地址所以要对a取地址(&)将值赋给指针p,也就是说这个指针p指向a. 很多新手都会对这两种定义方法

  • Go语言指针访问结构体的方法

    本文实例讲述了Go语言指针访问结构体的方法.分享给大家供大家参考.具体分析如下: Go有指针,但是没有指针运算. 结构体字段可以通过结构体指针来访问.通过指针间接的访问是透明的. 复制代码 代码如下: package main import "fmt" type Vertex struct {     X int     Y int } func main() {     p := Vertex{1, 2}     q := &p     q.X = 1e9     fmt.P

  • Swift与C语言指针结合使用实例

    Objective-C和C的API常常会需要用到指针.Swift中的数据类型都原生支持基于指针的Cocoa API,不仅如此,Swift会自动处理部分最常用的将指针作为参数传递的情况.这篇文章中,我们将着眼于在Swift中让C语言指针与变量.数组和字符串共同工作. ####用以输入/输出的参数指针 C和Objective-C并不支持多返回值,所以Cocoa API中常常将指针作为一种在方法间传递额外数据的方式.Swift允许指针被当作inout参数使用,所以你可以用符号&将对一个变量的引用作为指

  • C 语言指针变量详细介绍

    数据在内存中的地址也称为指针,如果一个变量存储了一份数据的指针,我们就称它为指针变量. 在C语言中,允许用一个变量来存放指针,这种变量称为指针变量.指针变量的值就是某份数据的地址,这样的一份数据可以是数组.字符串.函数,也可以是另外的一个普通变量或指针变量. 现在假设有一个 char 类型的变量 c,它存储了字符 'K'(ASCII码为十进制数 75),并占用了地址为 0X11A 的内存(地址通常用十六进制表示).另外有一个指针变量 p,它的值为 0X11A,正好等于变量 c 的地址,这种情况我

  • C语言 指针与数组的详解及区别

    C语言 指针与数组的详解及对比 通俗理解数组指针和指针数组 数组指针: eg:int( *arr)[10]; 数组指针通俗理解就是这个数组作为指针,指向某一个变量. 指针数组: eg:int*arr[10]; 指针数组简言之就是存放指针的数组: --数组并非指针&&指针并非数组 (1)定义一个外部变量: eg:int value=10; int *p=&value; 举例:当需要在一个函数中用这个变量时:externa int*p;而非extern int p[]; 分析:当用:e

  • C语言指针应用简单实例

    C语言指针应用简单实例 这次来说交换函数的实现: 1. #include <stdio.h> #include <stdlib.h> void swap(int x, int y) { int temp; temp = x; x = y; y = temp; } int main() { int a = 10, b = 20; printf("交换前:\n a = %d, b = %d\n", a, b); swap(a, b); printf("交换

  • C语言 指针变量作为函数参数详解

    在C语言中,函数的参数不仅可以是整数.小数.字符等具体的数据,还可以是指向它们的指针.用指针变量作函数参数可以将函数外部的地址传递到函数内部,使得在函数内部可以操作函数外部的数据,并且这些数据不会随着函数的结束而被销毁. 像数组.字符串.动态分配的内存等都是一系列数据的集合,没有办法通过一个参数全部传入函数内部,只能传递它们的指针,在函数内部通过指针来影响这些数据集合. 有的时候,对于整数.小数.字符等基本类型数据的操作也必须要借助指针,一个典型的例子就是交换两个变量的值. 有些初学者可能会使用

  • C语言 指针与二维数组详解

    二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有"缝隙".以下面的二维数组 a 为例: int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} }; 从概念上理解,a 的分布像一个矩阵: 0   1   2   3 4   5   6   7 8   9  10  11 但在内存中,a 的分布是一维线性的,整个数组占用一块连续的内存: C语言中的二维数组是按行排列的,也就是先存放 a[

随机推荐